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 e9f72234..06e59977 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java @@ -59,8 +59,9 @@ public class ClassProto implements TypeProto { @Nonnull protected final String type; @Nullable protected ClassDef classDef; @Nullable protected LinkedHashMap interfaces; - @Nullable protected Method[] vtable; + @Nullable protected List vtable; @Nullable protected SparseArray instanceFields; + protected boolean vtableFullyResolved = true; protected boolean interfacesFullyResolved = true; public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) { @@ -84,9 +85,9 @@ public class ClassProto implements TypeProto { } @Nonnull - Method[] getVtable() { + List getVtable() { if (vtable == null) { - vtable = loadVtable(); + loadVtable(); } return vtable; } @@ -346,11 +347,11 @@ public class ClassProto implements TypeProto { @Override @Nullable public MethodReference getMethodByVtableIndex(int vtableIndex) { - Method[] vtable = getVtable(); - if (vtableIndex < 0 || vtableIndex >= vtable.length) { + List vtable = getVtable(); + if (vtableIndex < 0 || vtableIndex >= vtable.size()) { return null; } - return vtable[vtableIndex]; + return vtable.get(vtableIndex); } @Nonnull @@ -552,66 +553,68 @@ public class ClassProto implements TypeProto { } //TODO: check the case when we have a package private method that overrides an interface method - @Nonnull - private Method[] loadVtable() { - List virtualMethodList = Lists.newLinkedList(); + private void loadVtable() { + vtable = Lists.newArrayList(); //copy the virtual methods from the superclass - String superclassType = getSuperclass(); + String superclassType; + try { + superclassType = getSuperclass(); + } catch (UnresolvedClassException ex) { + vtable.addAll(((ClassProto)classPath.getClass("Ljava/lang/Object;")).getVtable()); + vtableFullyResolved = false; + return; + } + if (superclassType != null) { ClassProto superclass = (ClassProto) classPath.getClass(superclassType); - for (int i=0; i localMethods, @Nonnull List vtable, - boolean replaceExisting) { + private void addToVtable(@Nonnull Iterable localMethods, + @Nonnull List vtable, boolean replaceExisting) { List methods = Lists.newArrayList(localMethods); Collections.sort(methods); - for (Method virtualMethod: methods) { - boolean found = false; + outer: for (Method virtualMethod: methods) { for (int i=0; i methods = classProto.getVtable(); + String className = "Class " + classDef.getType() + " extends " + classDef.getSuperclass() + " : " + methods.size() + " methods\n"; outStream.write(className.getBytes()); - for (int i=0;i" + methods[i].getName() + "("; - for (CharSequence parameter: methods[i].getParameterTypes()) { - method += parameter; + for (int i=0;i" + method.getName() + "("; + for (CharSequence parameter: method.getParameterTypes()) { + methodString += parameter; } - method += ")" + methods[i].getReturnType() + "\n"; - outStream.write(method.getBytes()); + methodString += ")" + method.getReturnType() + "\n"; + outStream.write(methodString.getBytes()); } outStream.write("\n".getBytes()); }