📄 reflect.c
字号:
WALK_DECLARED_METHODS(cb, mb, { CVMMethodTypeID nameAndTypeID = CVMmbNameAndTypeID(mb); CVMSigIterator parameters; CVMtypeidGetSignatureIterator( nameAndTypeID, ¶meters ); if (CVMmbIsSpecial(mb) && (!pub || CVMmbIs(mb, PUBLIC)) && (CVMtypeidIsConstructor(nameAndTypeID)) && (tcnt == (pcnt = CVM_SIGNATURE_ITER_PARAMCOUNT(parameters))) && (pcnt == 0 || CVMreflectMatchParameterTypes(ee, mb, types, pcnt))) { CVMreflectNewJavaLangReflectConstructor(ee, mb, result); return; } /* CVMreflectMatchParameterTypes can throw an exception */ if (CVMexceptionOccurred(ee)) { return; } }); nosuchmethod: CVMthrowNoSuchMethodException(ee, "<init>");}voidCVMreflectMethodBlockToNewJavaMethod(CVMExecEnv* ee, CVMMethodBlock* mb, CVMObjectICell* result){ /* %comment k003 */ if (CVMmbIsSpecial(mb)) CVMreflectNewJavaLangReflectConstructor(ee, mb, result); else CVMreflectNewJavaLangReflectMethod(ee, mb, result);}CVMMethodBlock*CVMreflectGCSafeGetMethodBlock(CVMExecEnv* ee, CVMObjectICell* method, CVMClassBlock* exceptionCb){ CVMMethodBlock* mb; CVMD_gcUnsafeExec(ee, { mb = CVMreflectGCUnsafeGetMethodBlock(ee, CVMID_icellDirect(ee, method), exceptionCb); }); return mb;}CVMMethodBlock*CVMreflectGCUnsafeGetMethodBlock(CVMExecEnv* ee, CVMObject* method, CVMClassBlock* exceptionCb){ const CVMClassBlock* classJavaLangReflectConstructor; const CVMClassBlock* classJavaLangReflectMethod; CVMClassBlock* cb; /* * Modify the member variable slot of type 'int' * and cast it to CVMMethodBlock*. 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 mbAsInt; CVMMethodBlock* mb; if (method == NULL) return NULL; classJavaLangReflectConstructor = CVMsystemClass(java_lang_reflect_Constructor); classJavaLangReflectMethod = CVMsystemClass(java_lang_reflect_Method); /* Test incoming object. Note this is not redundant because calling code is native code. */ cb = CVMobjectGetClass(method); CVMassert(cb != NULL); if ((cb != classJavaLangReflectConstructor) && (cb != classJavaLangReflectMethod)) { if (exceptionCb == NULL) { CVMthrowIllegalArgumentException(ee, NULL); } else { CVMsignalError(ee, exceptionCb, NULL); } return NULL; } /* NOTE: not 64-bit clean */ if (cb == classJavaLangReflectConstructor) { CVMD_fieldReadAddr(method, CVMoffsetOfjava_lang_reflect_Constructor_slot, mbAsInt); } else { CVMD_fieldReadAddr(method, CVMoffsetOfjava_lang_reflect_Method_slot, mbAsInt); } mb = (CVMMethodBlock*) mbAsInt; CVMassert(mb != NULL); return mb;}voidCVMreflectInterfaces(CVMExecEnv* ee, CVMClassBlock* cb, CVMArrayOfRefICell* result){ int i; if (CVMisArrayClass(cb)) { /* All arrays implement java.lang.Cloneable and java.io.Serializable */ CVMreflectNewClassArray(ee, 2, result); if (CVMID_icellIsNull(result)) return; /* exception already thrown */ CVMID_arrayWriteRef( ee, result, 0, CVMcbJavaInstance(CVMsystemClass(java_lang_Cloneable))); CVMID_arrayWriteRef( ee, result, 1, CVMcbJavaInstance(CVMsystemClass(java_io_Serializable))); } else { CVMreflectNewClassArray(ee, CVMcbImplementsCount(cb), result); if (CVMID_icellIsNull(result)) return; /* exception already thrown */ for (i = 0; i < CVMcbImplementsCount(cb); i++) { /* NOTE that the JDK performs some constant pool resolution here, but it's unnecessary for us since we resolve all implemented interfaces' classblocks at link time. */ CVMID_arrayWriteRef(ee, result, i, CVMcbJavaInstance(CVMcbInterfacecb(cb, i))); } }}voidCVMreflectInnerClasses(CVMExecEnv* ee, CVMClassBlock* cb, CVMArrayOfRefICell* result){ CVMConstantPool* cp = CVMcbConstantPool(cb); CVMClassBlock* icb; CVMConstantPool* icp; CVMClassBlock** member_cbs; int member_count = 0; CVMUint32 icount = CVMcbInnerClassesInfoCount(cb); CVMUint32 i, j; if (icount == 0) { /* Skip the work */ CVMreflectNewClassArray(ee, 0, result); return; } member_cbs = (CVMClassBlock**)malloc(icount * sizeof(CVMClassBlock*)); if (member_cbs == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return; } /* Find any "member" classes. */ for (i = 0; i < icount; i++) { CVMUint16 outerIdx = CVMcbInnerClassInfo(cb, i)->outerClassIndex; CVMUint16 innerIdx = CVMcbInnerClassInfo(cb, i)->innerClassIndex; CVMBool agree = CVM_FALSE; if (outerIdx == 0) { /* not a member */ continue; }#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, cb, cp, outerIdx)) { goto exception; }#endif if (CVMcpGetCb(cp, outerIdx) != cb) { continue; }#ifdef CVM_CLASSLOADING /* "cb" is the outer class, so this is a member */ if (!CVMcpResolveEntryFromClass(ee, cb, cp, innerIdx)) { goto exception; }#endif /* does member agree that "cb" is indeed its outer class? */ icb = CVMcpGetCb(cp, innerIdx); icp = CVMcbConstantPool(icb); for (j = 0; j < CVMcbInnerClassesInfoCount(icb); j++) { CVMUint16 i_outerIdx = CVMcbInnerClassInfo(icb, j)->outerClassIndex; CVMUint16 i_innerIdx = CVMcbInnerClassInfo(icb, j)->innerClassIndex;#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, icb, icp, i_innerIdx)) { goto exception; }#endif if (CVMcpGetCb(icp, i_innerIdx) != icb) { continue; } if (i_outerIdx == 0) { break; /* member says it is not a member; agree is FALSE. */ }#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, icb, icp, i_outerIdx)) { goto exception; }#endif if (CVMcpGetCb(icp, i_outerIdx) == cb) { member_cbs[member_count++] = CVMcpGetCb(cp, innerIdx); agree = CVM_TRUE; break; } } if (!agree) { CVMthrowIncompatibleClassChangeError( ee, "%C and %C disagree on InnerClasses attribute", cb, icb); goto exception; } } /* Allocate the result array */ CVMreflectNewClassArray(ee, member_count, result); if (CVMID_icellIsNull(result)) { /* exception */ goto exception; } for (i = 0; i < member_count; i++) { CVMID_arrayWriteRef(ee, result, i, CVMcbJavaInstance(member_cbs[i])); } exception: free(member_cbs);}CVMClassBlock*CVMreflectGetDeclaringClass(CVMExecEnv* ee, CVMClassBlock* cb){ CVMConstantPool* cp = CVMcbConstantPool(cb); CVMClassBlock* ocb; CVMConstantPool* ocp; CVMUint32 icount = CVMcbInnerClassesInfoCount(cb); CVMUint32 i, j; if (icount == 0) { /* neither an inner nor an outer class. */ return NULL; } for (i = 0; i < icount; i++) { CVMUint16 outerIdx = CVMcbInnerClassInfo(cb, i)->outerClassIndex; CVMUint16 innerIdx = CVMcbInnerClassInfo(cb, i)->innerClassIndex;#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, cb, cp, innerIdx)) { return NULL; }#endif if (CVMcpGetCb(cp, innerIdx) != cb) { continue; } /* "cb" is the inner class, so this must be the right record */ if (outerIdx == 0) { return NULL; /* not a member */ }#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, cb, cp, outerIdx)) { return NULL; }#endif /* does out class agree that "cb" is its member? */ ocb = CVMcpGetCb(cp, outerIdx); ocp = CVMcbConstantPool(ocb); for (j = 0; j < CVMcbInnerClassesInfoCount(ocb); j++) { CVMUint16 o_outerIdx = CVMcbInnerClassInfo(ocb, j)->outerClassIndex; CVMUint16 o_innerIdx = CVMcbInnerClassInfo(ocb, j)->innerClassIndex; if (o_outerIdx == 0) { continue; }#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, ocb, ocp, o_outerIdx)) { return NULL; }#endif if (CVMcpGetCb(ocp, o_outerIdx) != ocb) { continue; }#ifdef CVM_CLASSLOADING if (!CVMcpResolveEntryFromClass(ee, ocb, ocp, o_innerIdx)) { return NULL; }#endif if (CVMcpGetCb(ocp, o_innerIdx) == cb) { /* We verified both parties are in agreement. */ return CVMcpGetCb(cp, outerIdx); } } /* We found entry in "cb", but it doesn't agree with outer class. */ { CVMthrowIncompatibleClassChangeError( ee, "%C and %C disagree on InnerClasses attribute", cb, ocb); return NULL; } } return NULL;}/******************************************************************** * Utility routines from JDK 1.2's reflect_util.c (and others added) */CVMBoolCVMreflectCheckAccess(CVMExecEnv* ee, CVMClassBlock* memberClass, /* declaring class */ CVMUint32 acc, /* declared field or method access */ CVMClassBlock* targetClass, /* for protected */ CVMBool forInvoke, /* Is this being called from implementation of Method.invoke()? */ CVMClassBlock* exceptionCb){ CVMClassBlock* clientClass = NULL; /* Since we're going to be doing some private stuff here, let's make sure some invariants are met */ CVMassert(CVM_METHOD_ACC_PROTECTED == CVM_FIELD_ACC_PROTECTED);#define IsProtected(x) CVMmemberPPPAccessIs((x), FIELD, PROTECTED) CVMassert(ee != NULL); /* * The "client" is the class associated with the nearest frame * which has a "real" methodblock, i.e., is not a * reflection-related method (Method.invoke(), and on Dean's * suggestion, Constructor.newInstance() or Class.newInstance() as * well) or transition frame. getCallerClass already skips * Method.invoke frames, so pass 0 in that case. */ clientClass = CVMgetCallerClass(ee, (forInvoke) ? 0 : 1); if (clientClass != memberClass) { if (!CVMverifyClassAccess(ee, clientClass, memberClass, CVM_FALSE)) goto bad; if (!CVMverifyMemberAccess(ee, clientClass, memberClass, acc, CVM_FALSE)) goto bad; } /* * Additional test for protected members: JLS 6.6.2 * This could go faster if we had package objects */ if (IsProtected(acc)) if (targetClass != clientClass) if (!CVMisSameClassPackage(ee, clientClass, memberClass)) if (!CVMisSubclassOf(ee, targetClass, clientClass)) goto bad; /* Passed all tests */ return CVM_TRUE; bad: /* Already throw C stack overflow exception */ if (CVMlocalExceptionOccurred(ee)) { return CVM_FALSE; } else if (exceptionCb == NULL) { CVMthrowIllegalAccessException(ee, "%C", memberClass); } else { CVMsignalError(ee, exceptionCb, "%C", memberClass); } return CVM_FALSE;}voidCVMreflectNewArray(CVMExecEnv* ee, CVMClassBlock* cb, CVMInt32 length, CVMArrayOfAnyTypeICell* result){ /* Patterned after CVMjniNewObjectArray in jni_impl.c. */ CVMClassBlock* arrayCb = CVMclassGetArrayOf(ee, cb); if (arrayCb == NULL) { return; } if (CVMcbIs(cb, PRIMITIVE)) { CVMID_allocNewArray(ee, CVMcbBasicTypeCode(cb), arrayCb, length, (CVMObjectICell*) result); } else { CVMID_allocNewArray(ee, CVM_T_CLASS, arrayCb, length, (CVMObjectICell*) result); } if (CVMID_icellIsNull(result)) CVMthrowOutOfMemoryError(ee, "reflection: allocating new array");}voidCVMreflectNewClassArray(CVMExecEnv* ee, int length, CVMArrayOfRefICell* result){ const CVMClassBlock* classJavaLangClass = CVMsystemClass(java_lang_Class); /* Casting away const is safe here (see classes.h, runtime flags) */ CVMreflectNewArray(ee, (CVMClassBlock*) classJavaLangClass, length, (CVMArrayOfAnyTypeICell*) result);}#endif /* CVM_REFLECT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -