/* * 在'clazz'中,我们有一个方法指向另一个方法,但它可能指向派生类中的一个方法,我们想要从虚拟函数表中找到实际入口,如果'class'是一个接口,我们不得不在短时间内做更多的挖掘 * * 对于'direct'方法(private / constructor).我们仅仅返回原生态方法 * * (这里被适用于反射和JNI调用) */ const Method* dvmGetVirtualizedMethod(const ClassObject* clazz, const Method* meth) { Method* actualMeth; int methodIndex; if (dvmIsDirectMethod(meth)) { /* no vtable entry for these */ assert(!dvmIsStaticMethod(meth)); return meth; } /* * If the method was declared in an interface, we need to scan through * the class' list of interfaces for it, and find the vtable index * from that. * * TODO: use the interface cache. */ if (dvmIsInterfaceClass(meth->clazz)) { int i; for (i = 0; i < clazz->iftableCount; i++) { if (clazz->iftable[i].clazz == meth->clazz) break; } if (i == clazz->iftableCount) { dvmThrowIncompatibleClassChangeError( "invoking method from interface not implemented by class"); return NULL; } methodIndex = clazz->iftable[i].methodIndexArray[meth->methodIndex]; } else { methodIndex = meth->methodIndex; } assert(methodIndex >= 0 && methodIndex < clazz->vtableCount); actualMeth = clazz->vtable[methodIndex]; /* * Make sure there's code to execute. */ if (dvmIsAbstractMethod(actualMeth)) { dvmThrowAbstractMethodError(NULL); return NULL; } assert(!dvmIsMirandaMethod(actualMeth)); return actualMeth; }
/* * Convert a method pointer to a slot number. * * We use positive values starting from 0 for virtual methods, negative * values starting from -1 for static methods. */ static int methodToSlot(const Method* meth) { ClassObject* clazz = meth->clazz; int slot; if (dvmIsDirectMethod(meth)) { slot = meth - clazz->directMethods; assert(slot >= 0 && slot < clazz->directMethodCount); slot = -(slot+1); } else { slot = meth - clazz->virtualMethods; assert(slot >= 0 && slot < clazz->virtualMethodCount); } return slot; }