in core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreatorASM.java [3041:3572]
private <T> void genReadFieldValue(
ObjectReadContext context,
FieldReader fieldReader,
boolean fieldBased,
MethodWriterContext mwc,
int OBJECT,
int fieldReaderIndex,
boolean arrayMapping
) {
String classNameType = context.classNameType;
boolean jsonb = mwc.jsonb;
Class objectClass = context.objectClass;
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
long fieldFeatures = fieldReader.features;
String format = fieldReader.format;
Type itemType = fieldReader.itemType;
MethodWriter mw = mwc.mw;
if ((fieldFeatures & JSONReader.Feature.NullOnError.mask) != 0) {
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_FIELD_READE, "readFieldValue", METHOD_DESC_READ_FIELD_VALUE);
return;
}
Field field = fieldReader.field;
Method method = fieldReader.method;
Label endSet_ = new Label();
String TYPE_FIELD_CLASS = ASMUtils.type(fieldClass);
String DESC_FIELD_CLASS = ASMUtils.desc(fieldClass);
if (!(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
mw.aload(OBJECT);
}
int fieldModifier = 0;
if ((fieldBased || method == null) && field != null) {
fieldModifier = field.getModifiers();
}
if (fieldBased
&& Modifier.isPublic(objectClass.getModifiers())
&& Modifier.isPublic(fieldModifier)
&& !Modifier.isFinal(fieldModifier)
&& !classLoader.isExternalClass(objectClass)
) {
mw.checkcast(context.objectType);
}
if (fieldClass == boolean.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBoolValue", "()Z");
} else if (fieldClass == byte.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == short.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == int.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == long.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64Value", "()J");
} else if (fieldClass == float.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFloatValue", "()F");
} else if (fieldClass == double.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDoubleValue", "()D");
} else if (fieldClass == char.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readCharValue", "()C");
} else if (fieldClass == String.class) {
mw.aload(JSON_READER);
Label null_ = new Label();
mw.invokevirtual(TYPE_JSON_READER, "readString", "()Ljava/lang/String;");
mw.dup();
mw.ifnull(null_);
if ("trim".equals(format)) {
mw.invokevirtual("java/lang/String", "trim", "()Ljava/lang/String;");
} else if ("upper".equals(format)) {
mw.invokevirtual("java/lang/String", "toUpperCase", "()Ljava/lang/String;");
}
mw.visitLabel(null_);
} else if (fieldClass == Boolean.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBool", "()Ljava/lang/Boolean;");
} else if (fieldClass == Byte.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt8", "()Ljava/lang/Byte;");
} else if (fieldClass == Short.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt16", "()Ljava/lang/Short;");
} else if (fieldClass == Integer.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32", "()Ljava/lang/Integer;");
} else if (fieldClass == Long.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64", "()Ljava/lang/Long;");
} else if (fieldClass == Float.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFloat", "()Ljava/lang/Float;");
} else if (fieldClass == Double.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDouble", "()Ljava/lang/Double;");
} else if (fieldClass == BigDecimal.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBigDecimal", "()Ljava/math/BigDecimal;");
} else if (fieldClass == BigInteger.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBigInteger", "()Ljava/math/BigInteger;");
} else if (fieldClass == Number.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readNumber", "()Ljava/lang/Number;");
} else if (fieldClass == UUID.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readUUID", "()Ljava/util/UUID;");
} else if (fieldClass == LocalDate.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readLocalDate", "()Ljava/time/LocalDate;");
} else if (fieldClass == OffsetDateTime.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readOffsetDateTime", "()Ljava/time/OffsetDateTime;");
} else if (fieldClass == Date.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDate", "()Ljava/util/Date;");
} else if (fieldClass == Calendar.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readCalendar", "()Ljava/util/Calendar;");
} else {
Label endObject_ = new Label();
boolean disableReferenceDetect = context.disableReferenceDetect();
Integer REFERENCE = null;
if (!disableReferenceDetect) {
REFERENCE = mwc.var("REFERENCE");
}
if ((!disableReferenceDetect) && (!ObjectWriterProvider.isPrimitiveOrEnum(fieldClass))) {
Label endReference_ = new Label(), addResolveTask_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isReference", "()Z");
mw.ifeq(endReference_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readReference", "()Ljava/lang/String;");
if (context.objectClass == null || fieldClass.isAssignableFrom(context.objectClass)) {
mw.dup();
mw.astore(REFERENCE);
mw.visitLdcInsn("..");
mw.invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z");
mw.ifeq(addResolveTask_);
if (objectClass != null && fieldClass.isAssignableFrom(objectClass)) {
mw.aload(OBJECT);
// mw.visitTypeInsn(CHECKCAST, TYPE_FIELD_CLASS); // cast
mw.goto_(endObject_);
}
mw.visitLabel(addResolveTask_);
} else {
mw.astore(REFERENCE);
}
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.aload(REFERENCE);
mw.invokevirtual(TYPE_FIELD_READE, "addResolveTask", METHOD_DESC_ADD_RESOLVE_TASK);
mw.pop();
mw.goto_(endSet_);
mw.visitLabel(endReference_);
}
if (!fieldReader.fieldClassSerializable) {
Label endIgnoreCheck_ = new Label();
/*
* if ((features & Feature.IgnoreNoneSerializable.mask) != 0) {
* jsonReader.skipValue();
* goto endSet_;
* }
*/
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.IgnoreNoneSerializable.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(endIgnoreCheck_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
if (!(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
mw.pop();
}
mw.goto_(endSet_);
mw.visitLabel(endIgnoreCheck_);
}
boolean list = List.class.isAssignableFrom(fieldClass)
&& fieldReader.getInitReader() == null
&& !fieldClass.getName().startsWith("com.google.common.collect.Immutable");
if (list) {
Class itemClass = TypeUtils.getMapping(itemType);
if (itemClass != null
&& (Collection.class.isAssignableFrom(itemClass) || !Modifier.isPublic(itemClass.getModifiers()))
) {
list = false;
}
}
if (list && !fieldClass.isInterface() && !BeanUtils.hasPublicDefaultConstructor(fieldClass)) {
list = false;
}
if (list) {
genReadFieldValueList(
fieldReader,
classNameType,
mwc,
OBJECT,
fieldReaderIndex,
arrayMapping,
objectClass,
fieldClass,
fieldType,
fieldFeatures,
itemType,
TYPE_FIELD_CLASS,
context,
fieldBased
);
} else {
final String FIELD_OBJECT_READER = fieldObjectReader(fieldReaderIndex);
Label valueNotNull_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNull", "()Z");
mw.ifeq(valueNotNull_);
if (fieldClass == Optional.class) {
mw.invokestatic("java/util/Optional", "empty", "()Ljava/util/Optional;");
} else if (fieldClass == OptionalInt.class) {
mw.invokestatic("java/util/OptionalInt", "empty", "()Ljava/util/OptionalInt;");
} else if (fieldClass == OptionalLong.class) {
mw.invokestatic("java/util/OptionalLong", "empty", "()Ljava/util/OptionalLong;");
} else if (fieldClass == OptionalDouble.class) {
mw.invokestatic("java/util/OptionalDouble", "empty", "()Ljava/util/OptionalDouble;");
} else {
mw.aconst_null();
}
mw.goto_(endObject_);
mw.visitLabel(valueNotNull_);
if (fieldClass == String[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readStringArray", "()[Ljava/lang/String;");
} else if (fieldClass == int[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32ValueArray", "()[I");
} else if (fieldClass == long[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64ValueArray", "()[J");
} else {
if (Enum.class.isAssignableFrom(fieldClass) & !jsonb) {
genReadEnumValueRaw(
fieldReader,
classNameType,
mwc,
fieldReaderIndex,
fieldType,
fieldClass,
fieldFeatures,
FIELD_OBJECT_READER
);
} else {
genReadObject(
fieldReader,
classNameType,
mwc,
fieldReaderIndex,
fieldType,
fieldFeatures,
FIELD_OBJECT_READER
);
}
if (method != null
|| ((objectClass == null || Modifier.isPublic(objectClass.getModifiers()))
&& Modifier.isPublic(fieldModifier)
&& !Modifier.isFinal(fieldModifier)
&& !classLoader.isExternalClass(objectClass))
) {
mw.checkcast(TYPE_FIELD_CLASS); // cast
}
if (fieldReader.noneStaticMemberClass) {
try {
Field this0 = fieldClass.getDeclaredField("this$0");
long fieldOffset = UNSAFE.objectFieldOffset(this0);
Label notNull_ = new Label();
mw.dup();
mw.ifnull(notNull_);
mw.dup();
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.swap();
mw.visitLdcInsn(fieldOffset);
mw.aload(OBJECT);
mw.invokevirtual("sun/misc/Unsafe", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V");
mw.visitLabel(notNull_);
} catch (NoSuchFieldException e) {
// ignored
}
}
}
}
mw.visitLabel(endObject_);
}
if (field != null) {
String fieldClassName = fieldClass.getName();
boolean setDirect = (objectClass.getModifiers() & Modifier.PUBLIC) != 0
&& (fieldModifier & Modifier.PUBLIC) != 0
&& (fieldModifier & Modifier.FINAL) == 0
&& (ObjectWriterProvider.isPrimitiveOrEnum(fieldClass) || fieldClassName.startsWith("java.") || fieldClass.getClassLoader() == ObjectReaderProvider.FASTJSON2_CLASS_LOADER)
&& !classLoader.isExternalClass(objectClass)
&& field.getDeclaringClass() == objectClass;
if (setDirect) {
mw.putfield(context.objectType, field.getName(), DESC_FIELD_CLASS);
} else {
int FIELD_VALUE = mwc.var(fieldClass);
String methodName, methodDes;
int LOAD;
if (fieldClass == int.class) {
methodName = "putInt";
methodDes = "(Ljava/lang/Object;JI)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == long.class) {
methodName = "putLong";
methodDes = "(Ljava/lang/Object;JJ)V";
mw.lstore(FIELD_VALUE);
LOAD = Opcodes.LLOAD;
} else if (fieldClass == float.class) {
methodName = "putFloat";
methodDes = "(Ljava/lang/Object;JF)V";
mw.fstore(FIELD_VALUE);
LOAD = Opcodes.FLOAD;
} else if (fieldClass == double.class) {
methodName = "putDouble";
methodDes = "(Ljava/lang/Object;JD)V";
mw.dstore(FIELD_VALUE);
LOAD = Opcodes.DLOAD;
} else if (fieldClass == char.class) {
methodName = "putChar";
methodDes = "(Ljava/lang/Object;JC)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == byte.class) {
methodName = "putByte";
methodDes = "(Ljava/lang/Object;JB)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == short.class) {
methodName = "putShort";
methodDes = "(Ljava/lang/Object;JS)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == boolean.class) {
methodName = "putBoolean";
methodDes = "(Ljava/lang/Object;JZ)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else {
methodName = "putObject";
methodDes = "(Ljava/lang/Object;JLjava/lang/Object;)V";
mw.astore(FIELD_VALUE);
LOAD = Opcodes.ALOAD;
}
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.swap();
mw.visitLdcInsn(
UNSAFE.objectFieldOffset(field));
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokevirtual("sun/misc/Unsafe", methodName, methodDes);
}
} else if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
if (!fieldClass.isPrimitive()) {
mw.checkcast(ASMUtils.type(fieldClass));
}
mw.storeLocal(fieldClass, mwc.var(fieldReader));
} else {
boolean invokeFieldReaderAccept = context.externalClass || method == null || !context.publicClass;
if (invokeFieldReaderAccept) {
int FIELD_VALUE = mwc.var(fieldClass);
String acceptMethodDesc;
int LOAD;
if (fieldClass == boolean.class) {
acceptMethodDesc = "(Ljava/lang/Object;Z)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == byte.class) {
acceptMethodDesc = "(Ljava/lang/Object;B)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == short.class) {
acceptMethodDesc = "(Ljava/lang/Object;S)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == int.class) {
acceptMethodDesc = "(Ljava/lang/Object;I)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == long.class) {
acceptMethodDesc = "(Ljava/lang/Object;J)V";
mw.lstore(FIELD_VALUE);
LOAD = Opcodes.LLOAD;
} else if (fieldClass == char.class) {
acceptMethodDesc = "(Ljava/lang/Object;C)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == float.class) {
acceptMethodDesc = "(Ljava/lang/Object;F)V";
mw.fstore(FIELD_VALUE);
LOAD = Opcodes.FLOAD;
} else if (fieldClass == double.class) {
acceptMethodDesc = "(Ljava/lang/Object;D)V";
mw.dstore(FIELD_VALUE);
LOAD = Opcodes.DLOAD;
} else {
acceptMethodDesc = "(Ljava/lang/Object;Ljava/lang/Object;)V";
mw.astore(FIELD_VALUE);
LOAD = Opcodes.ALOAD;
}
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
BiConsumer function = fieldReader.getFunction();
if (function instanceof FieldBiConsumer) {
FieldBiConsumer fieldBiConsumer = (FieldBiConsumer) function;
mw.invokevirtual(TYPE_FIELD_READE, "getFunction", "()Ljava/util/function/BiConsumer;");
mw.checkcast(type(FieldBiConsumer.class));
mw.getfield(type(FieldBiConsumer.class), "consumer", desc(FieldConsumer.class));
mw.swap();
mw.visitLdcInsn(fieldBiConsumer.fieldIndex);
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokeinterface(type(FieldConsumer.class), "accept", "(Ljava/lang/Object;ILjava/lang/Object;)V");
} else {
mw.swap();
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokevirtual(TYPE_FIELD_READE, "accept", acceptMethodDesc);
}
} else {
Class<?> returnType = method.getReturnType();
String methodName = method.getName();
String methodDesc = null;
if (returnType == Void.TYPE) {
if (fieldClass == boolean.class) {
methodDesc = "(Z)V";
} else if (fieldClass == byte.class) {
methodDesc = "(B)V";
} else if (fieldClass == short.class) {
methodDesc = "(S)V";
} else if (fieldClass == int.class) {
methodDesc = "(I)V";
} else if (fieldClass == long.class) {
methodDesc = "(J)V";
} else if (fieldClass == char.class) {
methodDesc = "(C)V";
} else if (fieldClass == float.class) {
methodDesc = "(F)V";
} else if (fieldClass == double.class) {
methodDesc = "(D)V";
} else if (fieldClass == Boolean.class) {
methodDesc = "(Ljava/lang/Boolean;)V";
} else if (fieldClass == Integer.class) {
methodDesc = "(Ljava/lang/Integer;)V";
} else if (fieldClass == Long.class) {
methodDesc = "(Ljava/lang/Long;)V";
} else if (fieldClass == Float.class) {
methodDesc = "(Ljava/lang/Float;)V";
} else if (fieldClass == Double.class) {
methodDesc = "(Ljava/lang/Double;)V";
} else if (fieldClass == BigDecimal.class) {
methodDesc = "(Ljava/math/BigDecimal;)V";
} else if (fieldClass == String.class) {
methodDesc = "(Ljava/lang/String;)V";
} else if (fieldClass == UUID.class) {
methodDesc = "(Ljava/util/UUID;)V";
} else if (fieldClass == List.class) {
methodDesc = "(Ljava/util/List;)V";
} else if (fieldClass == Map.class) {
methodDesc = "(Ljava/util/Map;)V";
}
}
if (methodDesc == null) {
methodDesc = "(" + DESC_FIELD_CLASS + ")" + ASMUtils.desc(returnType);
}
mw.invokevirtual(context.objectType, methodName, methodDesc);
if (returnType != void.class) {
mw.pop();
}
}
// TODO BUILD METHOD
}
mw.visitLabel(endSet_);
}