📄 field.c
字号:
together since we're fundamentally dealing with either 32- or 64-bit values anyway */ switch (fromType) { case CVM_T_BOOLEAN: CVMD_fieldReadInt(obj, CVMfbOffset(declaringClassFb), v.z); break; case CVM_T_CHAR: CVMD_fieldReadInt(obj, CVMfbOffset(declaringClassFb), v.c); break; case CVM_T_FLOAT: CVMD_fieldReadFloat(obj, CVMfbOffset(declaringClassFb), v.f); break; case CVM_T_DOUBLE: CVMD_fieldReadDouble(obj, CVMfbOffset(declaringClassFb), v.d); break; case CVM_T_BYTE: CVMD_fieldReadInt(obj, CVMfbOffset(declaringClassFb), v.b); break; case CVM_T_SHORT: CVMD_fieldReadInt(obj, CVMfbOffset(declaringClassFb), v.s); break; case CVM_T_INT: CVMD_fieldReadInt(obj, CVMfbOffset(declaringClassFb), v.i); break; case CVM_T_LONG: CVMD_fieldReadLong(obj, CVMfbOffset(declaringClassFb), v.j); break; default: CVMthrowInternalError(ee, "java.lang.reflect.Field." "getPrimitiveField(): " "getting Java value. " "A non-primitive class " "showed up as primitive."); return CNI_EXCEPTION; } } else { switch (fromType) { case CVM_T_BOOLEAN: v.z = CVMfbStaticField(ee, declaringClassFb).i; break; case CVM_T_CHAR: v.c = CVMfbStaticField(ee, declaringClassFb).i; break; case CVM_T_FLOAT: v.f = CVMfbStaticField(ee, declaringClassFb).f; break; case CVM_T_DOUBLE: v.d = CVMjvm2Double(&CVMfbStaticField(ee, declaringClassFb).raw); break; case CVM_T_BYTE: v.b = CVMfbStaticField(ee, declaringClassFb).i; break; case CVM_T_SHORT: v.s = CVMfbStaticField(ee, declaringClassFb).i; break; case CVM_T_INT: v.i = CVMfbStaticField(ee, declaringClassFb).i; break; case CVM_T_LONG: v.j = CVMjvm2Long(&CVMfbStaticField(ee, declaringClassFb).raw); break; default: CVMthrowInternalError(ee, "java.lang.reflect.Field." "getPrimitiveField(): " "getting Java value. " "A non-primitive class showed up " "as primitive."); return CNI_EXCEPTION; } } /* Note we leave frame->topOfStack untouched, because it is decached by the interpreter when we return, but it is very important that we don't offer a GC-safe point after mutating the stack slot(s) corresponding to the return value because of possible changes of refness, which would make the stackmap incorrect. */ /* Attempt to widen the primitive value. If this fails then we throw an IllegalArgumentException. */ if (fromType != destinationType) REFLECT_WIDEN(v, fromType, destinationType, fail); REFLECT_SET(&arguments[0].j, destinationType, v); if (destinationType == CVM_T_DOUBLE || destinationType == CVM_T_LONG) return CNI_DOUBLE; else return CNI_SINGLE; fail: CVMthrowIllegalArgumentException(ee, "java.lang.reflect.Field." "getPrimitiveField(): " "widening primitive value"); return CNI_EXCEPTION; } else { CVMthrowIllegalArgumentException(ee, "java.lang.reflect.Field." "getPrimitiveField(): " "attempt to get object " "field as primitive"); return CNI_EXCEPTION; }}#endif /* CVM_REFLECT */CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getBoolean(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_BOOLEAN);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getByte(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_BYTE);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getChar(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_CHAR);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getShort(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_SHORT);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getInt(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_INT);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getLong(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_LONG);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getFloat(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_FLOAT);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_getDouble(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){ /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {});#ifdef CVM_REFLECT return CVMgetPrimitiveField(ee, arguments, p_mb, CVM_T_DOUBLE);#else /* CVM_REFLECT */ CVMthrowUnsupportedOperationException(ee, NULL); return CNI_EXCEPTION;#endif /* CVM_REFLECT */}CNIEXPORT CNIResultCodeCNIjava_lang_reflect_Field_set(CVMExecEnv* ee, CVMStackVal32 *arguments, CVMMethodBlock **p_mb){#ifdef CVM_REFLECT CVMObject* fieldObj; CVMObject* obj = NULL; CVMObject* argObj; CVMObject* fieldTypeObj; CVMFieldBlock* declaringClassFb; CVMClassBlock* declaringClassCb; /* * fieldTypeCbAddr holds a native pointer as an int value * therefore change the type to CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms */ CVMAddr fieldTypeCbAddr; CVMClassBlock* fieldTypeCb; CVMClassBlock* objectCb; CVMInt32 override; jvalue v; CVMBasicType fromType, toType; /* CNI policy: offer a gc-safe checkpoint */ CVMD_gcSafeCheckPoint(ee, {}, {}); fieldObj = CVMID_icellDirect(ee, &arguments[0].j.r); /* Can this happen? */ if (fieldObj == NULL) { CVMthrowNullPointerException(ee, "java.lang.reflect.Field.set(): " "null Field object"); return CNI_EXCEPTION; } /* Get the declaring class's fieldblock corresponding to the Field object. */ declaringClassFb = CVMreflectGCUnsafeGetFieldBlock(fieldObj); CVMassert(declaringClassFb != NULL); /* Get the declaring class of this field (note that the "class" field in java.lang.reflect.Field is redundant) */ declaringClassCb = CVMfbClassBlock(declaringClassFb); CVMassert(declaringClassCb != NULL); /* See whether the field is static. If so, we ignore the object argument. */ if (CVMfbIs(declaringClassFb, STATIC)) { objectCb = declaringClassCb; } else { /* Check whether the object is a non-null instance of the declaring class. */ obj = CVMID_icellDirect(ee, &arguments[1].j.r); if (obj == NULL) { CVMthrowNullPointerException(ee, "java.lang.reflect.Field.set(): " "null argument object for non-static " "field reference"); return CNI_EXCEPTION; } objectCb = CVMobjectGetClass(obj); if (!(objectCb == declaringClassCb || CVMgcUnsafeIsInstanceOf(ee, obj, declaringClassCb))) { CVMthrowIllegalArgumentException(ee, "java.lang.reflect.Field.set(): " "argument object is of the wrong type"); return CNI_EXCEPTION; } } /* * Access checking (unless overridden by Field) */ CVMD_fieldReadInt(fieldObj, CVMoffsetOfjava_lang_reflect_AccessibleObject_override, override); if (!override) { if (!(CVMcbIs(declaringClassCb, PUBLIC) && CVMfbIs(declaringClassFb, PUBLIC))) { /* NOTE: we pass in CVM_TRUE for "forInvoke" because we used the CNI calling convention to enter this code, which doesn't push an intermediary frame which we would need to skip. See documentation for CVMreflectCheckAccess. */ if (!CVMreflectCheckAccess(ee, declaringClassCb, CVMfbAccessFlags(declaringClassFb), objectCb, CVM_TRUE, NULL)) return CNI_EXCEPTION; /* exception */ } } if (CVMfbIs(declaringClassFb, FINAL)) { CVMthrowIllegalAccessException(ee, "field is final"); return CNI_EXCEPTION; /* exception */ } CVMD_fieldReadRef(fieldObj, CVMoffsetOfjava_lang_reflect_Field_type, fieldTypeObj); /* Now get the classblock of the type of the field. */ /* * Access member variable of type 'int' * and cast it to a native pointer. The java type 'int' only garanties * 32 bit, but because one slot is used as storage space and * a slot is 64 bit on 64 bit platforms, it is possible * to store a native pointer without modification of * java source code. This assumes that all places in the C-code * are catched which set/get this member. */ CVMD_fieldReadAddr(fieldTypeObj, CVMoffsetOfjava_lang_Class_classBlockPointer, fieldTypeCbAddr); fieldTypeCb = (CVMClassBlock*) fieldTypeCbAddr; CVMassert(fieldTypeCb != NULL); /* Get the argument object */ argObj = CVMID_icellDirect(ee, &arguments[2].j.r); /* NOTE this is allowed to be NULL for non-primitive types */ if (CVMcbIs(fieldTypeCb, PRIMITIVE)) { if (argObj == NULL) { CVMthrowIllegalArgumentException(ee, "java.lang.reflect.Field.set(): " "null argument object for " "primitive field"); return CNI_EXCEPTION; } toType = CVMcbBasicTypeCode(fieldTypeCb); if (CVMgcUnsafeJavaUnwrap(ee, argObj, &v, &fromType, NULL) == CVM_FALSE) { return CNI_EXCEPTION; } if (fromType != toType) REFLECT_WIDEN(v, fromType, toType, fail); /* Now we have the value we want to set. Have to handle static and non-static fields differently. */ if (!CVMfbIs(declaringClassFb, STATIC)) { /* many of these cases could probably be folded together. I think the only issue is properly handling the values < 32 bits. */ switch (toType) { case CVM_T_BOOLEAN: CVMD_fieldWriteInt(obj, CVMfbOffset(declaringClassFb), v.z); break; case CVM_T_CHAR: CVMD_fieldWriteInt(obj, CVMfbOffset(declaringClassFb), v.c); break; case CVM_T_FLOAT: CVMD_fieldWriteFloat(obj, CVMfbOffset(declaringClassFb), v.f); break; case CVM_T_DOUBLE: CVMD_fieldWriteDouble(obj, CVMfbOffset(declaringClassFb), v.d); break; case CVM_T_BYTE: CVMD_fieldWriteInt(obj, CVMfbOffset(declaringClassFb), v.b); break; case CVM_T_SHORT: CVMD_fieldWriteInt(obj, CVMfbOffset(declaringClassFb), v.s); break; case CVM_T_INT: CVMD_fieldWriteInt(obj, CVMfbOffset(declaringClassFb), v.i); break; case CVM_T_LONG: CVMD_fieldWriteLong(obj, CVMfbOffset(declaringClassFb), v.j); break; default: CVMthrowInternalError(ee, "illegal primitive type"); return CNI_EXCEPTION; } } else { /* many of these cases could probably be folded together. I think the only issue is properly handling the values < 32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -