/*
* Get a method ID for an instance method.
*
+ * While Dalvik bytecode has distinct instructions for virtual, super,
+ * static, direct, and interface method invocation, JNI only provides
+ * two functions for acquiring a method ID. This call handles everything
+ * but static methods.
+ *
* JNI defines <init> as an instance method, but Dalvik considers it a
* "direct" method, so we have to special-case it here.
*
if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
assert(dvmCheckException(_self));
+ } else if (dvmIsInterfaceClass(clazz)) {
+ Method* meth = dvmFindInterfaceMethodHierByDescriptor(clazz, name, sig);
+ if (meth == NULL) {
+ dvmThrowExceptionFmt("Ljava/lang/NoSuchMethodError;",
+ "no method with name='%s' signature='%s' in interface %s",
+ name, sig, clazz->descriptor);
+ }
+ id = (jmethodID) meth;
} else {
- Method* meth;
-
- meth = dvmFindVirtualMethodHierByDescriptor(clazz, name, sig);
+ Method* meth = dvmFindVirtualMethodHierByDescriptor(clazz, name, sig);
if (meth == NULL) {
/* search private methods and constructors; non-hierarchical */
meth = dvmFindDirectMethodByDescriptor(clazz, name, sig);
{
DvmDex* pDvmDex = referrer->pDvmDex;
Method* resMethod;
- int i;
LOGVV("--- resolving interface method %d (referrer=%s)\n",
methodIdx, referrer->descriptor);
LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
methodName, methodSig, resClass->descriptor);
- resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
+ resMethod = dvmFindInterfaceMethodHier(resClass, methodName, &proto);
if (resMethod == NULL) {
- /* scan superinterfaces and superclass interfaces */
- LOGVV("+++ did not resolve immediately\n");
- for (i = 0; i < resClass->iftableCount; i++) {
- resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
- methodName, &proto);
- if (resMethod != NULL)
- break;
- }
-
- if (resMethod == NULL) {
- LOGVV("+++ unable to resolve method %s\n", methodName);
- return NULL;
- }
- } else {
- LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
- resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
+ dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
+ return NULL;
}
/* we're expecting this to be abstract */
/*
* Find a "virtual" method in a class. If we don't find it, try the
- * superclass.
+ * superclass. Does not examine interfaces.
*
* Returns NULL if the method can't be found. (Does not throw an exception.)
*/
/*
* Find a "virtual" method in a class. If we don't find it, try the
- * superclass.
+ * superclass. Does not examine interfaces.
*
* Returns NULL if the method can't be found. (Does not throw an exception.)
*/
}
/*
+ * Find a method in an interface. Searches superinterfaces.
+ *
+ * Returns NULL if the method can't be found. (Does not throw an exception.)
+ */
+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;
+}
+
+/*
+ * Find a method in an interface. Searches superinterfaces.
+ *
+ * Returns NULL if the method can't be found. (Does not throw an exception.)
+ */
+Method* dvmFindInterfaceMethodHier(const ClassObject* iface,
+ const char* methodName, const DexProto* proto)
+{
+ Method* resMethod = dvmFindVirtualMethod(iface, methodName, proto);
+ if (resMethod == NULL) {
+ /* scan superinterfaces and superclass interfaces */
+ int i;
+ for (i = 0; i < iface->iftableCount; i++) {
+ resMethod = dvmFindVirtualMethod(iface->iftable[i].clazz,
+ methodName, proto);
+ if (resMethod != NULL)
+ break;
+ }
+ }
+ return resMethod;
+}
+
+/*
* Find a "direct" method (static, private, or "<*init>").
*
* Returns NULL if the method can't be found. (Does not throw an exception.)
const DexProto* proto);
/*
+ * Find a method in an interface hierarchy.
+ */
+Method* dvmFindInterfaceMethodHierByDescriptor(const ClassObject* iface,
+ const char* methodName, const char* descriptor);
+Method* dvmFindInterfaceMethodHier(const ClassObject* iface,
+ const char* methodName, const DexProto* proto);
+
+/*
* Find the implementation of "meth" in "clazz".
*
* Returns NULL and throws an exception if not found.
ClassObject* resClass;
const DexMethodId* pMethodId;
Method* resMethod;
- int i;
LOGVV("--- resolving interface method %d (referrer=%s)\n",
methodIdx, referrer->descriptor);
LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
methodName, methodSig, resClass->descriptor);
- resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
+ resMethod = dvmFindInterfaceMethodHier(resClass, methodName, &proto);
if (resMethod == NULL) {
- LOGVV("+++ did not resolve immediately\n");
- for (i = 0; i < resClass->iftableCount; i++) {
- resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
- methodName, &proto);
- if (resMethod != NULL)
- break;
- }
-
- if (resMethod == NULL) {
- dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
- return NULL;
- }
- } else {
- LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
- resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
+ dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
+ return NULL;
}
LOGVV("--- found interface method %d (%s.%s)\n",