Interface methods in the vtable are called on current class, not interface.

During optimization Dalvik checks if method is invoked on an interface, which causes warnings or errors. To prevent this, we assume that the class we are generating vtable for implements the interface, invoke the interface method on that class and let Dalvik resolve it at runtime.
This commit is contained in:
Izzat Bahadirov 2013-06-15 23:21:05 -04:00
parent 01cfa02bfe
commit 805b247b7d

View File

@ -45,6 +45,7 @@ import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.Method; import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.immutable.ImmutableMethod;
import org.jf.util.ExceptionWithContext; import org.jf.util.ExceptionWithContext;
import org.jf.util.SparseArray; import org.jf.util.SparseArray;
@ -350,6 +351,7 @@ public class ClassProto implements TypeProto {
if (vtableIndex < 0 || vtableIndex >= vtable.size()) { if (vtableIndex < 0 || vtableIndex >= vtable.size()) {
return null; return null;
} }
return vtable.get(vtableIndex); return vtable.get(vtableIndex);
} }
@ -596,8 +598,22 @@ public class ClassProto implements TypeProto {
if (!isInterface()) { if (!isInterface()) {
addToVtable(getClassDef().getVirtualMethods(), vtable, true); addToVtable(getClassDef().getVirtualMethods(), vtable, true);
// assume that interface method is implemented in the current class, when adding it to vtable
// otherwise it looks like that method is invoked on an interface, which fails Dalvik's optimization checks
for (ClassDef interfaceDef: getDirectInterfaces()) { for (ClassDef interfaceDef: getDirectInterfaces()) {
addToVtable(interfaceDef.getVirtualMethods(), vtable, false); List<Method> interfaceMethods = Lists.newArrayList();
for (Method interfaceMethod: interfaceDef.getVirtualMethods()) {
ImmutableMethod method = new ImmutableMethod(
type,
interfaceMethod.getName(),
interfaceMethod.getParameters(),
interfaceMethod.getReturnType(),
interfaceMethod.getAccessFlags(),
interfaceMethod.getAnnotations(),
interfaceMethod.getImplementation());
interfaceMethods.add(method);
}
addToVtable(interfaceMethods, vtable, false);
} }
} }
return vtable; return vtable;