in core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreatorASM.java [4254:4597]
private Function createValueConsumer0(
Class objectClass,
FieldReader[] fieldReaderArray,
boolean bytes
) {
Constructor defaultConstructor = BeanUtils.getDefaultConstructor(objectClass, false);
if (defaultConstructor == null || !Modifier.isPublic(objectClass.getModifiers())) {
return null;
}
ClassWriter cw = new ClassWriter(
(e) -> objectClass.getName().equals(e) ? objectClass : null
);
String className = (bytes ? "VBACG_" : "VCACG_")
+ seed.incrementAndGet()
+ "_" + fieldReaderArray.length
+ "_" + objectClass.getSimpleName();
String classNameType;
String classNameFull;
Package pkg = ObjectReaderCreatorASM.class.getPackage();
if (pkg != null) {
classNameFull = packageName + '.' + className;
classNameType = classNameFull.replace('.', '/');
} else {
classNameType = className;
classNameFull = className;
}
String TYPE_OBJECT = ASMUtils.type(objectClass);
String DESC_OBJECT = ASMUtils.desc(objectClass);
cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "consumer", "Ljava/util/function/Consumer;");
cw.visitField(Opcodes.ACC_PUBLIC, "object", DESC_OBJECT);
cw.visit(
Opcodes.V1_8,
Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
classNameType,
"java/lang/Object",
new String[]{
bytes ? TYPE_BYTE_ARRAY_VALUE_CONSUMER : TYPE_CHAR_ARRAY_VALUE_CONSUMER
}
);
{
final int CONSUMER = 1;
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
"(Ljava/util/function/Consumer;)V",
32
);
mw.aload(THIS);
mw.invokespecial("java/lang/Object", "<init>", "()V");
mw.aload(THIS);
mw.aload(CONSUMER);
mw.putfield(classNameType, "consumer", "Ljava/util/function/Consumer;");
mw.return_();
mw.visitMaxs(3, 3);
}
{
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"beforeRow",
"(I)V",
32
);
mw.aload(THIS);
newObject(mw, TYPE_OBJECT, defaultConstructor);
mw.putfield(classNameType, "object", DESC_OBJECT);
mw.return_();
mw.visitMaxs(3, 3);
}
{
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"afterRow",
"(I)V",
32
);
mw.aload(THIS);
mw.getfield(classNameType, "consumer", "Ljava/util/function/Consumer;");
mw.aload(THIS);
mw.getfield(classNameType, "object", DESC_OBJECT);
mw.invokeinterface("java/util/function/Consumer", "accept", "(Ljava/lang/Object;)V");
mw.aload(THIS);
mw.aconst_null();
mw.putfield(classNameType, "object", DESC_OBJECT);
mw.return_();
mw.visitMaxs(3, 3);
}
{
final int ROW = 1, COLUMN = 2, BYTES = 3, OFF = 4, LEN = 5, CHARSET = 6;
String methodDesc;
if (bytes) {
methodDesc = "(II[BIILjava/nio/charset/Charset;)V";
} else {
methodDesc = "(II[CII)V";
}
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"accept",
methodDesc,
32
);
Label switch_ = new Label(), L0_ = new Label(), L1_ = new Label();
mw.iload(LEN);
mw.ifne(L0_);
mw.return_();
mw.visitLabel(L0_);
mw.iload(COLUMN);
mw.ifge(L1_);
mw.return_();
mw.visitLabel(L1_);
mw.iload(COLUMN);
mw.visitLdcInsn(fieldReaderArray.length);
mw.if_icmple(switch_);
mw.return_();
mw.visitLabel(switch_);
Label dflt = new Label();
Label[] labels = new Label[fieldReaderArray.length];
int[] columns = new int[fieldReaderArray.length];
for (int i = 0; i < columns.length; i++) {
columns[i] = i;
labels[i] = new Label();
}
mw.iload(COLUMN);
mw.visitLookupSwitchInsn(dflt, columns, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
FieldReader fieldReader = fieldReaderArray[i];
Field field = fieldReader.field;
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
mw.aload(THIS);
mw.getfield(classNameType, "object", DESC_OBJECT);
String DESC_FIELD_CLASS, DESC_METHOD;
if (fieldType == Integer.class
|| fieldType == int.class
|| fieldType == Short.class
|| fieldType == short.class
|| fieldType == Byte.class
|| fieldType == byte.class
) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseInt", bytes ? "([BII)I" : "([CII)I");
if (fieldType == short.class) {
DESC_FIELD_CLASS = "S";
DESC_METHOD = "(S)V";
} else if (fieldType == Short.class) {
mw.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
DESC_FIELD_CLASS = "Ljava/lang/Short;";
DESC_METHOD = "(Ljava/lang/Short;)V";
} else if (fieldType == byte.class) {
DESC_FIELD_CLASS = "B";
DESC_METHOD = "(B)V";
} else if (fieldType == Byte.class) {
mw.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
DESC_FIELD_CLASS = "Ljava/lang/Byte;";
DESC_METHOD = "(Ljava/lang/Byte;)V";
} else if (fieldType == int.class) {
DESC_FIELD_CLASS = "I";
DESC_METHOD = "(I)V";
} else {
mw.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
DESC_FIELD_CLASS = "Ljava/lang/Integer;";
DESC_METHOD = "(Ljava/lang/Integer;)V";
}
} else if (fieldType == Long.class || fieldType == long.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseLong", bytes ? "([BII)J" : "([CII)J");
if (fieldType == long.class) {
DESC_FIELD_CLASS = "J";
DESC_METHOD = "(J)V";
} else {
mw.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
DESC_FIELD_CLASS = "Ljava/lang/Long;";
DESC_METHOD = "(Ljava/lang/Long;)V";
}
} else if (fieldType == Float.class || fieldType == float.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseFloat", bytes ? "([BII)F" : "([CII)F");
if (fieldType == float.class) {
DESC_FIELD_CLASS = "F";
DESC_METHOD = "(F)V";
} else {
mw.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
DESC_FIELD_CLASS = "Ljava/lang/Float;";
DESC_METHOD = "(Ljava/lang/Float;)V";
}
} else if (fieldType == Double.class || fieldType == double.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseDouble", bytes ? "([BII)D" : "([CII)D");
if (fieldType == double.class) {
DESC_FIELD_CLASS = "D";
DESC_METHOD = "(D)V";
} else {
mw.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
DESC_FIELD_CLASS = "Ljava/lang/Double;";
DESC_METHOD = "(Ljava/lang/Double;)V";
}
} else if (fieldType == Boolean.class || fieldType == boolean.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseBoolean", bytes ? "([BII)Ljava/lang/Boolean;" : "([CII)Ljava/lang/Boolean;");
if (fieldType == boolean.class) {
mw.invokevirtual("java/lang/Boolean", "booleanValue", "()Z");
DESC_FIELD_CLASS = "Z";
DESC_METHOD = "(Z)V";
} else {
DESC_FIELD_CLASS = "Ljava/lang/Boolean;";
DESC_METHOD = "(Ljava/lang/Boolean;)V";
}
} else if (fieldType == Date.class) {
mw.new_("java/util/Date");
// long millis = DateUtils.parseMillis(bytes, off, len, charset);
mw.dup();
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
if (bytes) {
mw.aload(CHARSET);
mw.invokestatic(TYPE_DATE_UTILS, "parseMillis", "([BIILjava/nio/charset/Charset;)J");
} else {
mw.invokestatic(TYPE_DATE_UTILS, "parseMillis", "([CII)J");
}
mw.invokespecial("java/util/Date", "<init>", "(J)V");
DESC_FIELD_CLASS = "Ljava/util/Date;";
DESC_METHOD = "(Ljava/util/Date;)V";
} else if (fieldType == BigDecimal.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseBigDecimal", bytes ? "([BII)Ljava/math/BigDecimal;" : "([CII)Ljava/math/BigDecimal;");
DESC_FIELD_CLASS = "Ljava/math/BigDecimal;";
DESC_METHOD = "(Ljava/math/BigDecimal;)V";
} else {
mw.new_("java/lang/String");
mw.dup();
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
if (bytes) {
mw.aload(CHARSET);
mw.invokespecial("java/lang/String", "<init>", "([BIILjava/nio/charset/Charset;)V");
} else {
mw.invokespecial("java/lang/String", "<init>", "([CII)V");
}
if (fieldType == String.class) {
DESC_FIELD_CLASS = "Ljava/lang/String;";
DESC_METHOD = "(Ljava/lang/String;)V";
} else {
DESC_FIELD_CLASS = ASMUtils.desc(fieldClass);
if (fieldClass == char.class) {
DESC_METHOD = "(C)V";
} else {
DESC_METHOD = "(" + DESC_FIELD_CLASS + ")V";
}
mw.visitLdcInsn(fieldClass);
mw.invokestatic(TYPE_TYPE_UTILS, "cast", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
mw.checkcast(ASMUtils.type(fieldClass));
}
}
if (fieldReader.method != null) {
if (fieldReader.method.getReturnType() != void.class) {
return null;
}
mw.invokevirtual(TYPE_OBJECT, fieldReader.method.getName(), DESC_METHOD);
} else if (field != null) {
mw.putfield(TYPE_OBJECT, field.getName(), DESC_FIELD_CLASS);
} else {
return null;
}
mw.goto_(dflt);
}
mw.visitLabel(dflt);
mw.return_();
mw.visitMaxs(3, 3);
}
byte[] code = cw.toByteArray();
try {
Class<?> consumerClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
Constructor<?> constructor = consumerClass.getConstructor(Consumer.class);
return (c) -> {
try {
return constructor.newInstance(c);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new JSONException("create ByteArrayValueConsumer error", e);
}
};
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}