From 805b247b7d416961bd1a16884b9e63e8a40a998c Mon Sep 17 00:00:00 2001 From: Izzat Bahadirov Date: Sat, 15 Jun 2013 23:21:05 -0400 Subject: [PATCH] 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. --- .../org/jf/dexlib2/analysis/ClassProto.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java index 39953c42..0665f0c1 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java @@ -45,6 +45,7 @@ import org.jf.dexlib2.iface.Field; import org.jf.dexlib2.iface.Method; import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.ImmutableMethod; import org.jf.util.ExceptionWithContext; import org.jf.util.SparseArray; @@ -350,6 +351,7 @@ public class ClassProto implements TypeProto { if (vtableIndex < 0 || vtableIndex >= vtable.size()) { return null; } + return vtable.get(vtableIndex); } @@ -596,8 +598,22 @@ public class ClassProto implements TypeProto { if (!isInterface()) { 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()) { - addToVtable(interfaceDef.getVirtualMethods(), vtable, false); + List 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;