/* * Perform Proxy setup. */ bool dvmReflectProxyStartup() { /* * Standard methods we must provide in our proxy. */ Method* methE; Method* methH; Method* methT; Method* methF; methE = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "equals", "(Ljava/lang/Object;)Z"); methH = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "hashCode", "()I"); methT = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "toString", "()Ljava/lang/String;"); methF = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "finalize", "()V"); if (methE == NULL || methH == NULL || methT == NULL || methF == NULL) { LOGE("Could not find equals/hashCode/toString/finalize in Object\n"); return false; } gDvm.voffJavaLangObject_equals = methE->methodIndex; gDvm.voffJavaLangObject_hashCode = methH->methodIndex; gDvm.voffJavaLangObject_toString = methT->methodIndex; gDvm.voffJavaLangObject_finalize = methF->methodIndex; /* * The prototype signature needs to be cloned from a method in a * "real" DEX file. We declared this otherwise unused method just * for this purpose. */ ClassObject* proxyClass; Method* meth; proxyClass = dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;"); if (proxyClass == NULL) { LOGE("No java.lang.reflect.Proxy\n"); return false; } meth = dvmFindDirectMethodByDescriptor(proxyClass, "constructorPrototype", "(Ljava/lang/reflect/InvocationHandler;)V"); if (meth == NULL) { LOGE("Could not find java.lang.Proxy.constructorPrototype()\n"); return false; } gDvm.methJavaLangReflectProxy_constructorPrototype = meth; return true; }
/* * 在指定的接口中,根据'descriptor'查找匹配的方法,找不到则在它的父接口中继续查找 * * 如果方法没有被找到则返回NULL (方法没有被查找到,也不会抛出异常信息) * */ Method* dvmFindInterfaceMethodHierByDescriptor(const ClassObject* iface, const char* methodName, const char* descriptor) { Method* resMethod = dvmFindVirtualMethodByDescriptor(iface, methodName, descriptor); if (resMethod == NULL) { /* scan superinterfaces and superclass interfaces */ int i; for (i = 0; i < iface->iftableCount; i++) { resMethod = dvmFindVirtualMethodByDescriptor(iface->iftable[i].clazz, methodName, descriptor); if (resMethod != NULL) break; } } return resMethod; }
/* * Make an inline call for the "debug" interpreter, used when the debugger * or profiler is active. */ bool dvmPerformInlineOp4Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult, int opIndex) { Thread* self = dvmThreadSelf(); bool result; assert(opIndex >= 0 && opIndex < NELEM(gDvmInlineOpsTable)); #ifdef WITH_PROFILER /* * Populate the methods table on first use. It's possible the class * hasn't been resolved yet, so we need to do the full "calling the * method for the first time" routine. (It's probably okay to skip * the access checks.) * * Currently assuming that we're only inlining stuff loaded by the * bootstrap class loader. This is a safe assumption for many reasons. */ Method* method = gDvm.inlinedMethods[opIndex]; if (method == NULL) { ClassObject* clazz; clazz = dvmFindClassNoInit( gDvmInlineOpsTable[opIndex].classDescriptor, NULL); if (clazz == NULL) { LOGW("Warning: can't find class '%s'\n", clazz->descriptor); goto skip_prof; } method = dvmFindDirectMethodByDescriptor(clazz, gDvmInlineOpsTable[opIndex].methodName, gDvmInlineOpsTable[opIndex].methodSignature); if (method == NULL) method = dvmFindVirtualMethodByDescriptor(clazz, gDvmInlineOpsTable[opIndex].methodName, gDvmInlineOpsTable[opIndex].methodSignature); if (method == NULL) { LOGW("Warning: can't find method %s.%s %s\n", clazz->descriptor, gDvmInlineOpsTable[opIndex].methodName, gDvmInlineOpsTable[opIndex].methodSignature); goto skip_prof; } gDvm.inlinedMethods[opIndex] = method; IF_LOGV() { char* desc = dexProtoCopyMethodDescriptor(&method->prototype); LOGV("Registered for profile: %s.%s %s\n", method->clazz->descriptor, method->name, desc); free(desc); } }
Method* dvmFindInlinableMethod(const char* classDescriptor, const char* methodName, const char* methodSignature) { /* * Find the class. */ ClassObject* clazz = dvmFindClassNoInit(classDescriptor, NULL); if (clazz == NULL) { ALOGE("dvmFindInlinableMethod: can't find class '%s'", classDescriptor); dvmClearException(dvmThreadSelf()); return NULL; } /* * Method could be virtual or direct. Try both. Don't use * the "hier" versions. */ Method* method = dvmFindDirectMethodByDescriptor(clazz, methodName, methodSignature); if (method == NULL) { method = dvmFindVirtualMethodByDescriptor(clazz, methodName, methodSignature); } if (method == NULL) { ALOGE("dvmFindInlinableMethod: can't find method %s.%s %s", clazz->descriptor, methodName, methodSignature); return NULL; } /* * Check that the method is appropriate for inlining. */ if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) { ALOGE("dvmFindInlinableMethod: can't inline non-final method %s.%s", clazz->descriptor, method->name); return NULL; } if (dvmIsSynchronizedMethod(method) || dvmIsDeclaredSynchronizedMethod(method)) { ALOGE("dvmFindInlinableMethod: can't inline synchronized method %s.%s", clazz->descriptor, method->name); return NULL; } return method; }
static bool initVirtualMethodOffset(int* pOffset, const char* className, const char* name, const char* descriptor) { ClassObject* clazz = dvmFindSystemClassNoInit(className); if (clazz == NULL) { ALOGE("Could not find essential class %s for virtual method lookup", className); return false; } Method* method = dvmFindVirtualMethodByDescriptor(clazz, name, descriptor); if (method == NULL) { ALOGE("Could not find essential virtual method %s.%s with descriptor %s", clazz->descriptor, name, descriptor); return false; } *pOffset = method->methodIndex; return true; }