ASMUtils.java
package com.alibaba.fastjson2.internal.asm;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.fastjson2.function.*;
import com.alibaba.fastjson2.reader.*;
import com.alibaba.fastjson2.schema.JSONSchema;
import com.alibaba.fastjson2.util.IOUtils;
import com.alibaba.fastjson2.util.UnsafeUtils;
import com.alibaba.fastjson2.writer.*;
import com.alibaba.fastjson2.writer.FieldWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.*;
public class ASMUtils {
public static final String TYPE_UNSAFE_UTILS = UnsafeUtils.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_ADAPTER
= ObjectWriterAdapter.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_1 = ObjectWriter1.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_2 = ObjectWriter2.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_3 = ObjectWriter3.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_4 = ObjectWriter4.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_5 = ObjectWriter5.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_6 = ObjectWriter6.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_7 = ObjectWriter7.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_8 = ObjectWriter8.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_9 = ObjectWriter9.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_10 = ObjectWriter10.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_11 = ObjectWriter11.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER_12 = ObjectWriter12.class.getName().replace('.', '/');
public static final String TYPE_FIELD_READE = FieldReader.class.getName().replace('.', '/');
public static final String TYPE_JSON_READER = JSONReader.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER = ObjectReader.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_ADAPTER
= ObjectReaderAdapter.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_1 = ObjectReader1.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_2 = ObjectReader2.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_3 = ObjectReader3.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_4 = ObjectReader4.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_5 = ObjectReader5.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_6 = ObjectReader6.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_7 = ObjectReader7.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_8 = ObjectReader8.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_9 = ObjectReader9.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_10 = ObjectReader10.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_11 = ObjectReader11.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_READER_12 = ObjectReader12.class.getName().replace('.', '/');
public static final String TYPE_OBJECT_WRITER = ObjectWriter.class.getName().replace('.', '/');
public static final String TYPE_JSON_WRITER = JSONWriter.class.getName().replace('.', '/');
public static final String TYPE_FIELD_WRITER = FieldWriter.class.getName().replace('.', '/');
public static final String DESC_FIELD_WRITER = 'L' + FieldWriter.class.getName().replace('.', '/') + ';';
public static final String DESC_FIELD_WRITER_ARRAY = "[" + DESC_FIELD_WRITER;
public static final String DESC_FIELD_READER = 'L' + FieldReader.class.getName().replace('.', '/') + ';';
public static final String DESC_FIELD_READER_ARRAY = "[" + DESC_FIELD_READER;
public static final String DESC_JSON_READER = 'L' + TYPE_JSON_READER + ';';
public static final String DESC_JSON_WRITER = 'L' + TYPE_JSON_WRITER + ';';
public static final String DESC_OBJECT_READER = 'L' + TYPE_OBJECT_READER + ';';
public static final String DESC_OBJECT_WRITER = 'L' + TYPE_OBJECT_WRITER + ';';
public static final String DESC_SUPPLIER = "Ljava/util/function/Supplier;";
public static final String DESC_JSONSCHEMA = 'L' + JSONSchema.class.getName().replace('.', '/') + ';';
static Map<Class, String> descMapping = new HashMap<>();
static Map<Class, String> typeMapping = new HashMap<>();
static {
descMapping.put(int.class, "I");
descMapping.put(void.class, "V");
descMapping.put(boolean.class, "Z");
descMapping.put(char.class, "C");
descMapping.put(byte.class, "B");
descMapping.put(short.class, "S");
descMapping.put(float.class, "F");
descMapping.put(long.class, "J");
descMapping.put(double.class, "D");
typeMapping.put(int.class, "I");
typeMapping.put(void.class, "V");
typeMapping.put(boolean.class, "Z");
typeMapping.put(char.class, "C");
typeMapping.put(byte.class, "B");
typeMapping.put(short.class, "S");
typeMapping.put(float.class, "F");
typeMapping.put(long.class, "J");
typeMapping.put(double.class, "D");
Class[] classes = new Class[]{
String.class,
java.util.List.class,
java.util.Collection.class,
ObjectReader.class,
ObjectReader1.class,
ObjectReader2.class,
ObjectReader3.class,
ObjectReader4.class,
ObjectReader5.class,
ObjectReader6.class,
ObjectReader7.class,
ObjectReader8.class,
ObjectReader9.class,
ObjectReader10.class,
ObjectReader11.class,
ObjectReader12.class,
ObjectReaderAdapter.class,
FieldReader.class,
JSONReader.class,
ObjBoolConsumer.class,
ObjCharConsumer.class,
ObjByteConsumer.class,
ObjShortConsumer.class,
ObjIntConsumer.class,
ObjLongConsumer.class,
ObjFloatConsumer.class,
ObjDoubleConsumer.class,
BiConsumer.class,
UnsafeUtils.class,
ObjectWriterAdapter.class,
ObjectWriter1.class,
ObjectWriter2.class,
ObjectWriter3.class,
ObjectWriter4.class,
ObjectWriter5.class,
ObjectWriter6.class,
ObjectWriter7.class,
ObjectWriter8.class,
ObjectWriter9.class,
ObjectWriter10.class,
ObjectWriter11.class,
ObjectWriter12.class,
com.alibaba.fastjson2.writer.FieldWriter.class,
JSONPathCompilerReflect.SingleNamePathTyped.class,
JSONWriter.Context.class,
JSONB.class,
JSONSchema.class,
JSONType.class,
java.util.Date.class,
java.util.function.Supplier.class
};
for (Class objectType : classes) {
String type = objectType.getName().replace('.', '/');
typeMapping.put(objectType, type);
String desc = 'L' + type + ';';
descMapping.put(objectType, desc);
}
typeMapping.put(JSONWriter.class, TYPE_JSON_WRITER);
descMapping.put(JSONWriter.class, DESC_JSON_WRITER);
typeMapping.put(ObjectWriter.class, TYPE_OBJECT_WRITER);
descMapping.put(ObjectWriter.class, DESC_OBJECT_WRITER);
descMapping.put(FieldWriter[].class, DESC_FIELD_WRITER_ARRAY);
descMapping.put(FieldReader[].class, DESC_FIELD_READER_ARRAY);
}
public static String type(Class<?> clazz) {
String type = typeMapping.get(clazz);
if (type != null) {
return type;
}
if (clazz.isArray()) {
return "[" + desc(clazz.getComponentType());
}
// ���������������������������������������������������
return clazz.getName().replace('.', '/');
}
static final AtomicReference<char[]> descCacheRef = new AtomicReference<>();
public static String desc(Class<?> clazz) {
String desc = descMapping.get(clazz);
if (desc != null) {
return desc;
}
if (clazz.isArray()) {
Class<?> componentType = clazz.getComponentType();
return "[" + desc(componentType);
}
String className = clazz.getName();
char[] chars = descCacheRef.getAndSet(null);
if (chars == null) {
chars = new char[512];
}
chars[0] = 'L';
className.getChars(0, className.length(), chars, 1);
for (int i = 1; i < chars.length; i++) {
if (chars[i] == '.') {
chars[i] = '/';
}
}
chars[className.length() + 1] = ';';
String str = new String(chars, 0, className.length() + 2);
descCacheRef.compareAndSet(null, chars);
return str;
}
public static String[] lookupParameterNames(AccessibleObject methodOrCtor) {
if (methodOrCtor instanceof Constructor) {
Constructor constructor = (Constructor) methodOrCtor;
Class[] parameterTypes = constructor.getParameterTypes();
Class declaringClass = constructor.getDeclaringClass();
if (declaringClass == DateTimeParseException.class) {
if (parameterTypes.length == 3) {
if (parameterTypes[0] == String.class && parameterTypes[1] == CharSequence.class && parameterTypes[2] == int.class) {
return new String[]{"message", "parsedString", "errorIndex"};
}
} else if (parameterTypes.length == 4) {
if (parameterTypes[0] == String.class && parameterTypes[1] == CharSequence.class && parameterTypes[2] == int.class && parameterTypes[3] == Throwable.class) {
return new String[]{"message", "parsedString", "errorIndex", "cause"};
}
}
}
if (Throwable.class.isAssignableFrom(declaringClass)) {
switch (parameterTypes.length) {
case 1:
if (parameterTypes[0] == String.class) {
return new String[]{"message"};
}
if (Throwable.class.isAssignableFrom(parameterTypes[0])) {
return new String[]{"cause"};
}
break;
case 2:
if (parameterTypes[0] == String.class && Throwable.class.isAssignableFrom(parameterTypes[1])) {
return new String[]{"message", "cause"};
}
break;
default:
break;
}
}
}
final Class<?>[] types;
final Class<?> declaringClass;
final String name;
int paramCount;
if (methodOrCtor instanceof Method) {
Method method = (Method) methodOrCtor;
types = method.getParameterTypes();
name = method.getName();
declaringClass = method.getDeclaringClass();
paramCount = method.getParameterCount();
} else {
Constructor<?> constructor = (Constructor<?>) methodOrCtor;
types = constructor.getParameterTypes();
declaringClass = constructor.getDeclaringClass();
name = "<init>";
paramCount = constructor.getParameterCount();
}
if (types.length == 0) {
return new String[paramCount];
}
ClassLoader classLoader = declaringClass.getClassLoader();
if (classLoader == null) {
classLoader = ClassLoader.getSystemClassLoader();
}
String className = declaringClass.getName();
String resourceName = className.replace('.', '/') + ".class";
InputStream is = classLoader.getResourceAsStream(resourceName);
if (is == null) {
return new String[paramCount];
}
try {
ClassReader reader = new ClassReader(is);
TypeCollector visitor = new TypeCollector(name, types);
reader.accept(visitor);
String[] params = visitor.getParameterNamesForMethod();
if (params != null && params.length == paramCount - 1) {
Class<?> dd = declaringClass.getDeclaringClass();
if (dd != null && dd.equals(types[0])) {
String[] strings = new String[paramCount];
strings[0] = "this$0";
System.arraycopy(params, 0, strings, 1, params.length);
params = strings;
}
}
return params;
} catch (IOException e) {
return new String[paramCount];
} finally {
IOUtils.close(is);
}
}
}