📄 reflect.c
字号:
CVMMethodBlock* mb, CVMObjectICell* result){ CVMClassBlock* returnType; 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 mbPtr; CVMMethodTypeID nameAndTypeID; CVMSigIterator parameters; char* methodName; CVMUint32 modifiers; const CVMClassBlock* classJavaLangReflectMethod = CVMsystemClass(java_lang_reflect_Method); /* Casting away const is safe here (see classes.h, runtime flags) */ CVMID_allocNewInstance(ee, (CVMClassBlock*) classJavaLangReflectMethod, result); if (CVMID_icellIsNull(result)) { CVMthrowOutOfMemoryError(ee, "CVMreflectNewJavaLangReflectMethod: " "out of memory allocating Method object"); return; } /* Fill in fields. */ /* Store Java class in which this field is contained */ cb = CVMmbClassBlock(mb); CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Method_clazz, CVMcbJavaInstance(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. */ mbPtr = (CVMAddr) mb; CVMID_fieldWriteAddr(ee, result, CVMoffsetOfjava_lang_reflect_Method_slot, mbPtr); nameAndTypeID = CVMmbNameAndTypeID(mb); CVMtypeidGetSignatureIterator( nameAndTypeID, ¶meters ); CVMID_localrootBegin(ee); { CVMID_localrootDeclare(CVMArrayOfRefICell, parameterTypes); CVMID_localrootDeclare(CVMArrayOfRefICell, checkedExceptions); /* Parameter types */ CVMreflectGetParameterTypes(ee, ¶meters, cb, parameterTypes); if (CVMID_icellIsNull(parameterTypes)) /* exception occurred */ { CVMID_icellSetNull(result); goto abort; } CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Method_parameterTypes, (CVMObjectICell*) parameterTypes); /* Return type */ returnType = CVMclassLookupByTypeFromClass( ee, CVM_SIGNATURE_ITER_RETURNTYPE(parameters), CVM_FALSE, cb); if (returnType == NULL) { /* exception occurred */ CVMID_icellSetNull(result); goto abort; } CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Method_returnType, CVMcbJavaInstance(returnType)); /* Checked exception types */ CVMreflectGetExceptionTypes(ee, cb, mb, checkedExceptions); if (CVMID_icellIsNull(checkedExceptions)) /* exception occurred */ { CVMID_icellSetNull(result); goto abort; } CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Method_exceptionTypes, (CVMObjectICell*) checkedExceptions); /* Store method name as Java String. */ methodName = CVMtypeidMethodNameToAllocatedCString(nameAndTypeID); if (methodName == NULL) { CVMID_icellSetNull(result); CVMthrowOutOfMemoryError(ee, "CVMreflectNewJavaLangReflectMethod: " "out of memory allocating method name"); goto abort; } { CVMBool success; CVMID_localrootDeclare(CVMObjectICell, methodNameICell); CVMnewStringUTF(ee, methodNameICell, methodName); success = !CVMID_icellIsNull(methodNameICell); CVMID_fieldWriteRef(ee, result, CVMoffsetOfjava_lang_reflect_Method_name, methodNameICell); free(methodName); if (!success) { CVMID_icellSetNull(result); CVMthrowOutOfMemoryError(ee, NULL); goto abort; } } /* 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 (CVMmbIs(mb, PUBLIC)) modifiers |= java_lang_reflect_Modifier_PUBLIC; if (CVMmbIs(mb, PRIVATE)) modifiers |= java_lang_reflect_Modifier_PRIVATE; if (CVMmbIs(mb, PROTECTED)) modifiers |= java_lang_reflect_Modifier_PROTECTED; if (CVMmbIs(mb, STATIC)) modifiers |= java_lang_reflect_Modifier_STATIC; if (CVMmbIs(mb, FINAL)) modifiers |= java_lang_reflect_Modifier_FINAL; if (CVMmbIs(mb, SYNCHRONIZED)) modifiers |= java_lang_reflect_Modifier_SYNCHRONIZED; if (CVMmbIs(mb, NATIVE)) modifiers |= java_lang_reflect_Modifier_NATIVE; if (CVMmbIs(mb, ABSTRACT)) modifiers |= java_lang_reflect_Modifier_ABSTRACT; if (CVMmbIsJava(mb) && CVMjmdIs(CVMmbJmd(mb), STRICT)) modifiers |= java_lang_reflect_Modifier_STRICT; CVMID_fieldWriteInt(ee, result, CVMoffsetOfjava_lang_reflect_Method_modifiers, modifiers); CVMID_fieldWriteInt(ee, result, CVMoffsetOfjava_lang_reflect_AccessibleObject_override, CVM_FALSE); }abort: CVMassert(CVMID_icellIsNull(result) == CVMlocalExceptionOccurred(ee)); CVMID_localrootEnd();}/** Tell us whether this methodblock is <init> or <clinit>; returns CVMBool. */#define CVMmbIsSpecial(mb) \ (CVMtypeidIsConstructor(CVMmbNameAndTypeID(mb)) || \ CVMtypeidIsStaticInitializer(CVMmbNameAndTypeID(mb))) voidCVMreflectMethods(CVMExecEnv* ee, CVMClassBlock* cb, int which, CVMArrayOfRefICell* result){ CVMBool mustAbort = CVM_FALSE; const CVMClassBlock* classJavaLangReflectMethod = CVMsystemClass(java_lang_reflect_Method); if (CVMcbIs(cb, PRIMITIVE)) { /* Allocate zero-length array of java.lang.reflect.Method objects */ /* Casting away const is safe here (see classes.h, runtime flags) */ CVMreflectNewArray(ee, (CVMClassBlock*) classJavaLangReflectMethod, 0, (CVMArrayOfAnyTypeICell*) result); return; } CVMreflectEnsureLinked(ee, cb); switch (which) { case REFLECT_MEMBER_PUBLIC: { /* NOTE: this discrepancy between the treatment of interfaces and regular classes comes about because interfaces re-use their interface array as a flattened hierarchy of their superinterfaces and also contain themselves in that table. The reason for this self-reference is to make construction of a real class's interface array easier; it is then simply the concatenation of the interface arrays of all its implemented interfaces. See classes.h for more details. */ CVMBool isInterface = CVMcbIs(cb, INTERFACE); int cnt = 0, j; CVMMethodBlock **interfaceMBs = NULL; if (isInterface) { int newCnt = 0; /* All interface methods are public */ WALK_INTERFACE_METHODS(cb, mb, cnt++); interfaceMBs = malloc(cnt * sizeof(CVMMethodBlock *)); if (interfaceMBs == NULL) { CVMthrowOutOfMemoryError(ee, NULL); return; } WALK_INTERFACE_METHODS(cb, mb, { int i; for (i = 0; i < newCnt; i++) { CVMMethodTypeID nameAndTypeID = CVMmbNameAndTypeID(mb); if (nameAndTypeID == CVMmbNameAndTypeID(interfaceMBs[i])) { break; } } if (i == newCnt) { interfaceMBs[newCnt] = mb; newCnt++; } }); cnt = newCnt; } else { /* Count public instance methods */ /* NOTE: CVMmbIsSpecial #defined above, in this file, not in classes.h */ WALK_INSTANCE_METHODS(cb, mb, { if (CVMmbIs(mb, PUBLIC) && !CVMmbIsSpecial(mb)) cnt++; }); /* Count public static methods */ /* NOTE: CVMmbIsSpecial #defined above, in this file, not in classes.h */ WALK_SUPER_METHODS(cb, mb, { if (CVMmbIs(mb, PUBLIC) && CVMmbIs(mb, STATIC) && !CVMmbIsSpecial(mb)) cnt++; }); } /* Allocate array of java.lang.reflect.Method objects */ /* Casting away const is safe here (see classes.h, runtime flags) */ CVMreflectNewArray(ee, (CVMClassBlock*) classJavaLangReflectMethod, cnt, (CVMArrayOfAnyTypeICell*) result); if (CVMID_icellIsNull(result)) { /* exception occurred */ if (interfaceMBs != NULL) { free(interfaceMBs); } return; } /* Fill array in declaration order */ j = cnt; CVMID_localrootBegin(ee); { CVMID_localrootDeclare(CVMObjectICell, methodICell); if (isInterface) { int i; CVMassert(interfaceMBs != NULL); for(i =0; i < cnt; i++) { CVMMethodBlock *mb = interfaceMBs[i]; CVMassert(mb != NULL); CVMreflectNewJavaLangReflectMethod(ee, mb, methodICell); if (CVMID_icellIsNull(methodICell)) { /* exception occurred */ CVMID_icellSetNull(result); /* Must execute CVMID_localrootEnd() */ mustAbort = CVM_TRUE; goto abort1; } CVMID_arrayWriteRef(ee, result, i, methodICell); } CVMwithAssertsOnly(j -= i); } else { /* Gather public instance methods */ /* NOTE: CVMmbIsSpecial #defined above, in this file, not in classes.h */ WALK_INSTANCE_METHODS(cb, mb, { if (CVMmbIs(mb, PUBLIC) && !CVMmbIsSpecial(mb)) { CVMreflectNewJavaLangReflectMethod(ee, mb, methodICell); if (CVMID_icellIsNull(methodICell)) { /* exception occurred */ CVMID_icellSetNull(result); /* Must execute CVMID_localrootEnd() */ mustAbort = CVM_TRUE; goto abort1; } j--; CVMID_arrayWriteRef(ee, result, j, methodICell); } }); /* Gather public static methods */ /* NOTE: CVMmbIsSpecial #defined above, in this file, not in classes.h */ WALK_SUPER_METHODS(cb, mb, { if (CVMmbIs(mb, PUBLIC) && CVMmbIs(mb, STATIC) && !CVMmbIsSpecial(mb)) { CVMreflectNewJavaLangReflectMethod(ee, mb, methodICell); if (CVMID_icellIsNull(methodICell)) { /* exception occurred */ CVMID_icellSetNull(result); /* Must execute CVMID_localrootEnd() */ mustAbort = CVM_TRUE; goto abort1; } j--; CVMID_arrayWriteRef(ee, result, j, methodICell); } }); } } abort1: CVMID_localrootEnd(); if (interfaceMBs != NULL) { free(interfaceMBs); } if (mustAbort) return; CVMassert(j == 0); break; } case REFLECT_MEMBER_DECLARED: { CVMInt32 cnt = 0, j; /* Filter out static initializers and constructors */ /* NOTE: CVMmbIsSpecial #defined above, in this file, not in classes.h */ WALK_DECLARED_METHODS(cb, mb, { if (!CVMmbIsSpecial(mb)) cnt++; }); /* Allocate array of java.lang.reflect.Method objects */ /* Casting away const is safe here (see classes.h, runtime flags) */ CVMreflectNewArray(ee, (CVMClassBlock*) classJavaLangReflectMethod, cnt, (CVMArrayOfAnyTypeICell*) result); if (CVMID_icellIsNull(result)) /* exception occurred */ return; /* Fill array in declaration order */ j = cnt; CVMID_localrootBegin(ee); { CVMID_localrootDeclare(CVMObjectICell, methodICell); /* Filter out static initializers and constructors */ WALK_DECLARED_METHODS(cb, mb, { if (!CVMmbIsSpecial(mb)) { CVMreflectNewJavaLangReflectMethod(ee, mb, methodICell); if (CVMID_icellIsNull(methodICell)) { /* exception occurred */ CVMID_icellSetNull(result); /* Must execute CVMID_localrootEnd() */ mustAbort = CVM_TRUE; goto abort2; } j--; CVMID_arrayWriteRef(ee, result, j, methodICell); } }); } abort2: CVMID_localrootEnd(); if (mustAbort) return; CVMassert(j == 0); break; } default: CVMassert(CVM_FALSE); }}CVMBoolCVMreflectMatchParameterTypes(CVMExecEnv *ee, CVMMethodBlock* mb, CVMArrayOfRefICell* classes, CVMInt32 cnt){ CVMBool mustAbort = CVM_FALSE; CVMMethodTypeID nameAndTypeID = CVMmbNameAndTypeID(mb); CVMSigIterator signature; CVMClassTypeID p; CVMClassBlock* cb; CVMClassBlock* cbFromSig; CVMClassBlock* cbFromArray; CVMInt32 i = 0; /* * Modify the member variable slot of type 'int' * and cast it to CVMClassBlock*. 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 cbAsInt; CVMtypeidGetSignatureIterator( nameAndTypeID, &signature); cb = CVMmbClassBlock(mb); CVMID_localrootBegin(ee); { CVMID_localrootDeclare(CVMObjectICell, classICell); while ( (p = CVM_SIGNATURE_ITER_NEXT( signature ) ) != CVM_TYPEID_ENDFUNC ){ /* * The match must be exact, not by name. This can be slow... */ cbFromSig = CVMclassLookupByTypeFromClass(ee, p, CVM_FALSE, cb ); if (cbFromSig == NULL) { /* exception: Must execute CVMID_localrootEnd() */ mustAbort = CVM_TRUE; goto abort; } CVMID_arrayReadRef(ee, classes, i, classICell); i++; /* This can be an assertion because the class can't be NULL at this point (see CVMreflectNewJavaLangReflectMethod) */ CVMassert(!CVMID_icellIsNull(classICell)); /* Get classblock out of java.lang.Class object */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -