📄 reflect.c
字号:
/* We don't need to check for throwing OutOfMemoryError since CVMreflectNewJavaLangReflectField does it already */ goto finish; } }); break; } default: CVMassert(CVM_FALSE); } CVMthrowNoSuchFieldException(ee, "%s", name); finish: if (nameCookie != CVM_TYPEID_ERROR) { CVMtypeidDisposeMembername(ee, nameCookie); }}voidCVMreflectNewJavaLangReflectField(CVMExecEnv* ee, CVMFieldBlock* fb, CVMObjectICell* result){ const CVMClassBlock* classJavaLangReflectField = CVMsystemClass(java_lang_reflect_Field); CVMClassBlock* cb; /* Store raw fieldblock pointer as int */ /* * Modify the member variable slot of type 'int' * and cast it to CVMFieldBlock*. The java type 'int' only guarantees * 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 * which set/get this member are caught. */ CVMAddr fbPtr; CVMFieldTypeID nameAndTypeID; char* fieldName; CVMClassBlock* fieldTypeClassBlock; CVMUint32 modifiers; /* Casting away const is safe here (see classes.h, runtime flags) */ CVMID_allocNewInstance(ee, (CVMClassBlock*) classJavaLangReflectField, result); if (CVMID_icellIsNull(result)) { CVMthrowOutOfMemoryError(ee, "CVMreflectNewJavaLangReflectField: " "out of memory allocating Field object"); return; } /* Fill in fields. */ /* Store Java class in which this field is contained */ cb = CVMfbClassBlock(fb); CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Field_clazz, CVMcbJavaInstance(cb)); /* Store raw fieldblock pointer as int (NOTE: not 64-bit clean) */ /* * Modify the member variable slot of type 'int' * and cast it to CVMFieldBlock*. The java type 'int' only guarantees * 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 * which set/get this member are caught. */ fbPtr = (CVMAddr) fb; CVMID_fieldWriteAddr(ee, result, CVMoffsetOfjava_lang_reflect_Field_slot, fbPtr); /* Store field name as Java String. */ nameAndTypeID = CVMfbNameAndTypeID(fb); fieldName = CVMtypeidFieldNameToAllocatedCString(nameAndTypeID); if (fieldName == NULL) { /* %comment c019 */ CVMthrowOutOfMemoryError(ee, "CVMreflectNewJavaLangReflectField: " "out of memory getting field name"); CVMID_icellSetNull(result); return; } { CVMBool success; CVMID_localrootBegin(ee); { CVMID_localrootDeclare(CVMObjectICell, fieldNameICell); CVMnewStringUTF(ee, fieldNameICell, fieldName); success = !CVMID_icellIsNull(fieldNameICell); CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Field_name, fieldNameICell); } CVMID_localrootEnd(); free(fieldName); if (!success) { CVMthrowOutOfMemoryError(ee, NULL); CVMID_icellSetNull(result); return; } } /* Store the Class object representing the type of this field. */ fieldTypeClassBlock = CVMclassLookupByTypeFromClass(ee, CVMtypeidGetType(nameAndTypeID), CVM_FALSE, cb); /* It's possible that loading the field type's classblock threw an exception. */ if (fieldTypeClassBlock == NULL) { CVMID_icellSetNull(result); return; } CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Field_type, CVMcbJavaInstance(fieldTypeClassBlock)); /* Store this field's modifiers. */ /* Make sure we use the constants defined by the JVM spec as opposed to any renumbered ones in the VM. We get these from java.lang.reflect.Modifier via JavaCodeCompact. */ modifiers = 0; if (CVMfbIs(fb, PUBLIC)) modifiers |= java_lang_reflect_Modifier_PUBLIC; if (CVMfbIs(fb, PRIVATE)) modifiers |= java_lang_reflect_Modifier_PRIVATE; if (CVMfbIs(fb, PROTECTED)) modifiers |= java_lang_reflect_Modifier_PROTECTED; if (CVMfbIs(fb, STATIC)) modifiers |= java_lang_reflect_Modifier_STATIC; if (CVMfbIs(fb, FINAL)) modifiers |= java_lang_reflect_Modifier_FINAL; if (CVMfbIs(fb, VOLATILE)) modifiers |= java_lang_reflect_Modifier_VOLATILE; if (CVMfbIs(fb, TRANSIENT)) modifiers |= java_lang_reflect_Modifier_TRANSIENT; CVMID_fieldWriteInt(ee, result, CVMoffsetOfjava_lang_reflect_Field_modifiers, modifiers);}CVMFieldBlock*CVMreflectGCSafeGetFieldBlock(CVMExecEnv* ee, CVMObjectICell* obj){ CVMFieldBlock* fb; CVMD_gcUnsafeExec(ee, { fb = CVMreflectGCUnsafeGetFieldBlock(CVMID_icellDirect(ee, obj)); }); return fb;}CVMFieldBlock*CVMreflectGCUnsafeGetFieldBlock(CVMObject* obj){ /* * Modify the member variable slot of type 'int' * and cast it to CVMFieldBlock*. The java type 'int' only guarantees * 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 * which set/get this member are caught. */ CVMAddr val; CVMFieldBlock* fb; CVMD_fieldReadAddr(obj, CVMoffsetOfjava_lang_reflect_Field_slot, val); fb = (CVMFieldBlock*) val; CVMassert(fb != NULL); return fb;}/* * Code supporting reflection: used by Method.c * * NOTE (from JDK 1.2, might not be applicable): Some of this should * be replaced by direct JNI calls, as the JNI already provides much * of the necessary functionality. */#define GET_ARRAY_LENGTH(ee,object,result) \ if ((object == NULL) || CVMID_icellIsNull((object))) { \ (result) = 0; \ } else { \ CVMID_arrayGetLength((ee), (object), (result)); \ }/* NOTE: unused "CVMreflectInvocationTargetException" removed. *//* Elided GET_CLASS_METHODBLOCK and GET_METHODBLOCK_SLOT macros since they're designed to make methodblock accesses 64-bit clean, but so much of the code is already unclean, it's not worth it. Actually, it probably wouldn't be THAT much work to make the field accesses (for example) 64-bit clean, but you'd have to add another field to java.lang.reflect.Field for a pointer to the FieldRange and use the slot as an index into it. There are issues about whether C pointers and Java references are guaranteed to be the same size. */CVMMethodBlock*CVMreflectGetObjectMethodblock(CVMExecEnv* ee, CVMClassBlock* ocb, CVMMethodBlock* mb){ /* Get declaring class of given methodblock */ CVMClassBlock* dcb = CVMmbClassBlock(mb); CVMMethodBlock* omb; CVMassert(!CVMmbIs(mb, STATIC)); /* OCB should have been linked by the time we get in here; see javavm/native/java/lang/reflect/Method.c. The class is ensured to have been initialized, which means it has been linked. */ CVMassert(CVMcbCheckRuntimeFlag(ocb, LINKED)); CVMassert(!CVMcbIs(ocb, INTERFACE)); if (CVMcbIs(dcb, INTERFACE)) { /* * Interface method lookup * An interface method's offset is its index in the interface */ CVMInt32 icount = CVMcbInterfaceCount(ocb), i; for (i = 0; i < icount; i++) { if (dcb == CVMcbInterfacecb(ocb, i)) { /* This class implements the requested interface. Use the precomputed offsets to get the method block. See executejava.c for better comments on this process. */ CVMInt32 methodIndex = CVMcbInterfaceMethodTableIndex(ocb, i, CVMmbMethodSlotIndex(mb)); omb = CVMcbMethodTableSlot(ocb, methodIndex); goto found; } } goto nosuchmethod; } /* CVMcbIs(dcb, INTERFACE) */ else if (CVMmbIs(mb, PRIVATE)) { /* Private methods are not in the dispatch table */ omb = mb; } /* CVMmbIs(mb, PRIVATE) */ else { /* * Dynamic method lookup. */ /* NOTE: what if the method is public but final, and declared final in the base class? It seems (romjava.c) that such methods show up in the method table even though they don't need to. Why is this? */ omb = CVMcbMethodTableSlot(ocb, CVMmbMethodTableIndex(mb)); } /* !CVMcbIs(cb, INTERFACE) && !CVMmbIs(mb, PRIVATE) */found: CVMassert(CVMtypeidIsSame(CVMmbNameAndTypeID(mb), CVMmbNameAndTypeID(omb))); return omb;nosuchmethod: CVMsignalError(ee, CVMsystemClass(java_lang_reflect_Method_ArgumentException), "%C.%M", CVMmbClassBlock(mb), mb); return NULL;}intCVMreflectGetParameterCount(CVMMethodTypeID sig){ CVMterseSig tsig; CVMtypeidGetTerseSignature( sig, &tsig ); CVMassert(CVM_TERSE_PARAMCOUNT(tsig) >= 0 ); return CVM_TERSE_PARAMCOUNT(tsig);}voidCVMreflectGetParameterTypes(CVMExecEnv* ee, CVMSigIterator *sigp, CVMClassBlock* cb, CVMArrayOfRefICell* result){ CVMInt32 cnt, i = 0; CVMClassBlock* pcb; CVMClassTypeID p; /* * Compute number of parameters */ cnt = CVM_SIGNATURE_ITER_PARAMCOUNT(*sigp); /* * Allocate class array */ CVMreflectNewClassArray(ee, cnt, result); if (CVMID_icellIsNull(result)) /* error */ return; /* * Resolve parameter types to classblocks */ while ((p=CVM_SIGNATURE_ITER_NEXT(*sigp)) != CVM_TYPEID_ENDFUNC) { pcb = CVMclassLookupByTypeFromClass(ee, p, CVM_FALSE, cb); if (pcb == NULL) { CVMID_icellSetNull(result); return; } CVMID_arrayWriteRef(ee, result, i, CVMcbJavaInstance(pcb)); i++; } CVMassert(i == cnt);}voidCVMreflectGetExceptionTypes(CVMExecEnv* ee, CVMClassBlock* cb, CVMMethodBlock* mb, CVMArrayOfRefICell* result){ CVMCheckedExceptions* checkedExceptions; CVMUint16 cnt = 0; checkedExceptions = CVMmbCheckedExceptions(mb); if (checkedExceptions != NULL) cnt = checkedExceptions->numExceptions; CVMreflectNewClassArray(ee, cnt, result); if (CVMID_icellIsNull(result)) /* error */ return; if (cnt != 0) { CVMUint16 i; for (i = 0; i < cnt; i++) { CVMClassBlock *exceptioncb;#ifdef CVM_CLASSLOADING /* Must ensure these constant pool entries are resolved to classblocks */ if (!CVMcpResolveEntryFromClass(ee, cb, CVMcbConstantPool(cb), checkedExceptions->exceptions[i])) { /* Exception already thrown */ CVMID_icellSetNull(result); return; }#endif exceptioncb = CVMcpGetCb(CVMcbConstantPool(cb), checkedExceptions->exceptions[i]); CVMID_arrayWriteRef(ee, result, i, CVMcbJavaInstance(exceptioncb)); } }}CVMBoolCVMreflectGCUnsafePushArg(CVMExecEnv* ee, CVMFrame* currentJavaFrame, CVMObject* arg, CVMClassBlock* argType, CVMClassBlock* exceptionCb){ if (CVMcbIs(argType, PRIMITIVE)) { jvalue v; CVMBasicType declaredTypeCode = CVMcbBasicTypeCode(argType); CVMBasicType valueTypeCode; CVMUint32 numBytes; if (CVMgcUnsafeJavaUnwrap(ee, arg, &v, &valueTypeCode, exceptionCb) == CVM_FALSE) return CVM_FALSE; /* exception */ if (valueTypeCode != declaredTypeCode) REFLECT_WIDEN(v, valueTypeCode, declaredTypeCode, bad); REFLECT_SET(currentJavaFrame->topOfStack, declaredTypeCode, v); numBytes = CVMbasicTypeSizes[declaredTypeCode]; /* * For any 64-bit ports that (unnecessarily) allocate two "Slots" * for Longs and Doubles we have to accept 16 Bytes as well. * For "single slot" Longs and Doubles * this should be reverted to the original state. */#ifdef CVM_64 CVMassert((numBytes == 1) || (numBytes == 2) || (numBytes == 4) || (numBytes == 8) || (numBytes == 16));#else CVMassert((numBytes == 1) || (numBytes == 2) || (numBytes == 4) || (numBytes == 8));#endif currentJavaFrame->topOfStack += (numBytes > sizeof(CVMJavaVal32)) ? 2 : 1; return CVM_TRUE; } else { CVMBool retVal; retVal = CVMgcUnsafeIsInstanceOf(ee, arg, argType); if (retVal == CVM_TRUE) { /* arg is an instance of argType */ CVMID_icellSetDirect(ee, (CVMObjectICell *) currentJavaFrame->topOfStack, arg); (currentJavaFrame->topOfStack)++; return CVM_TRUE; } }bad: if (exceptionCb == NULL) CVMthrowIllegalArgumentException(ee, "argument type mismatch"); else CVMsignalError(ee, exceptionCb, "argument type mismatch"); return CVM_FALSE;}/* NOTE: unused "CVMreflectPopResult" removed. *//* NOTE: invoke() functionality moved to javavm/native/java/lang/reflect/Method.c and Constructor.c. *//* * Support code for class Class native code */voidCVMreflectNewJavaLangReflectMethod(CVMExecEnv* ee,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -