I encountered a problem when using Proguard(version 6.0.3) in my android project.
Below is the stack of exceptions:(I am sorry that some code info of our program was replaceed by xxx/a/)
Ignoring unused library classes... Original number of library classes: 6448 Final number of library classes: 2187 Printing kept classes, fields, and methods... Inlining subroutines... Obfuscating... Printing mapping to [/root/workspace/xxx/build/outputs/mapping/xxx/release/mapping.txt]... Preverifying... Unexpected error while performing partial evaluation: Class = [xxx/a/b] Method = [a(Ljava/lang/String;)V] Exception = [java.lang.IllegalArgumentException] (Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes)) Unexpected error while preverifying:
First of all,i guess that there must be something wrong with my compilation(such as modify our program classes) or a bug of proguard in obfuscating process(we had turned off optimization )。So i tried to modify proguard and add a preverifying process before obfuscating ,below is the changes:
public void execute() throws IOException { ... readInput(); ... if (configuration.addConfigurationDebugging) { addConfigurationLogging(); } //**********added************* if (configuration.preverify) { preverify(); } if (configuration.printSeeds != null) { printSeeds(); } ... if (configuration.preverify) { preverify(); } .... }
And i ran compilation again and the exceptiion(stack is same as before) still occured.
Ignoring unused library classes... Original number of library classes: 6448 Final number of library classes: 2187 Preverifying... Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes) 0 aload_1 v1 popCount 0 pushCount 1 inst lenth 1 1 ldc #214 popCount 0 pushCount 1 inst lenth 2 3 invokestatic #49 popCount 2 pushCount 0 inst lenth 3 6 aload_0 v0 popCount 0 pushCount 1 inst lenth 1 7 aload_1 v1 popCount 0 pushCount 1 inst lenth 1 8 putfield #75 popCount 2 pushCount 0 inst lenth 3 11 aload_0 v0 popCount 0 pushCount 1 inst lenth 1 12 getfield #19 popCount 1 pushCount 1 inst lenth 3 15 checkcast #29 popCount 1 pushCount 1 inst lenth 3 18 dup popCount 1 pushCount 2 inst lenth 1 19 ifnull +18 popCount 1 pushCount 0 inst lenth 3 22 invokevirtual #32 popCount 1 pushCount 1 inst lenth 3 25 dup popCount 1 pushCount 2 inst lenth 1 26 ifnull +11 popCount 1 pushCount 0 inst lenth 3 29 invokeinterface #217, 256 popCount 1 pushCount 0 inst lenth 5 34 goto +4 popCount 0 pushCount 0 inst lenth 3 37 pop popCount 1 pushCount 0 inst lenth 1 38 aload_0 v0 popCount 0 pushCount 1 inst lenth 1 39 iconst_0 popCount 0 pushCount 1 inst lenth 1 40 putfield #83 popCount 2 pushCount 0 inst lenth 3 43 return popCount 0 pushCount 0 inst lenth 1 Unexpected error while performing partial evaluation: Class = [xxx/a/b] Method = [restore(Ljava/lang/String;)V] Exception = [java.lang.IllegalArgumentException] (Can't find common super class of [xxx/a/c] (with 1 known super classes) and [java/util/List] (with 2 known super classes)) Unexpected error while preverifying:
Note:I have changed code of proguard and print the bytecode of method while exception occured
According to the log,we could find the location where the exception throwed:
/** * Returns the most specific common superclass or interface of the given * classes. * @param class1 the first class. * @param class2 the second class. * @param interfaces specifies whether to look for a superclass or for an * interface. * @return the common class. */ private Clazz findCommonClass(Clazz class1, Clazz class2, boolean interfaces) { // Collect the superclasses or the interfaces of this class. ... if (commonClass == null) { throw new IllegalArgumentException("Can't find common super class of ["+ class1.getName() +"] (with "+superClasses1Count +" known super classes) and ["+ class2.getName()+"] (with "+superClasses2Count+" known super classes)"); } ... return commonClass; }
I was shocked that why preverifier goes to find common super class bettwen xxx/a/c and java/util/List
So, there should be a problem with the bytecode(location:xxx/a/b.restore) before proguard and i found the class.Here is the bytecode(before as a program input) of method 'xxx/a/b.restore':
// access flags 0x11 public final restore(Ljava/lang/String;)V // annotable parameter count: 1 (invisible) @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0 L0 ALOAD 1 LDC "requestId" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L1 LINENUMBER 105 L1 ALOAD 0 ALOAD 1 PUTFIELD xxx/a/b.requestSessionId : Ljava/lang/String; L2 LINENUMBER 106 L2 ALOAD 0 GETFIELD xxx/a/b.mData : Ljava/lang/Object; CHECKCAST xxx/a/c DUP IFNULL L3 INVOKEVIRTUAL xxx/a/c.getAwemeList ()Ljava/util/List; DUP IFNULL L3 INVOKEINTERFACE java/util/List.clear ()V (itf) GOTO L4 L3 FRAME SAME1 java/lang/Object POP L4 LINENUMBER 107 L4 FRAME SAME ALOAD 0 ICONST_0 PUTFIELD xxx/a/b.mCursor : I L5 LINENUMBER 108 L5 RETURN L6 LOCALVARIABLE this Lxxx/a/b; L0 L6 0 LOCALVARIABLE requestId Ljava/lang/String; L0 L6 1 MAXSTACK = 2 MAXLOCALS = 2
The source code was writtern by koltin and much like below:
package xxx.a class b:d<c>(){ ... 104 fun restore(requestId: String) { 105 requestSessionId = requestId 106 mData?.awemeList?.clear() 107 mCursor = 0 108 } ... }
And then,i had tried to find something bad within the bytecode but everything is legall.
And then,i had tried to find something different bytecode bettwen the xxx/a/b.restore and the outcome of kotlin compilation but it is no different(Around java/util/List),Below is the outcome bytecode of kotlin compilation:
// access flags 0x11 public final restore(Ljava/lang/String;)V // annotable parameter count: 1 (visible) // annotable parameter count: 1 (invisible) @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0 L0 ALOAD 1 LDC "requestId" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L1 LINENUMBER 105 L1 ALOAD 0 ALOAD 1 PUTFIELD xxx/a/b.requestSessionId : Ljava/lang/String; L2 LINENUMBER 106 L2 ALOAD 0 GETFIELD xxx/a/b.mData : Ljava/lang/Object; CHECKCAST xxx/a/c DUP IFNULL L3 INVOKEVIRTUAL xxx/a/c.getAwemeList ()Ljava/util/List; DUP IFNULL L3 INVOKEINTERFACE java/util/List.clear ()V (itf) GOTO L4 L3 POP L4 L5 LINENUMBER 107 L5 ALOAD 0 ICONST_0 PUTFIELD xxx/a/b.mCursor : I L6 LINENUMBER 108 L6 RETURN L7 LOCALVARIABLE this Lxxx/a/b; L0 L7 0 LOCALVARIABLE requestId Ljava/lang/String; L0 L7 1 MAXSTACK = 2 MAXLOCALS = 2
And then,i guessed It's a bug in the verification process .I tried to turned off verification and ran on my app and found tha the app was working fine,with no crash.
So,i think it is a bug of proguard。
Note:I have tried the latest version(6.2.0) and it still no work.
link of diff image:https://s2.ax1x.com/2019/10/12/uOWzpq.png
Last edit: Mr Yang 2019-10-12
Thank you for your extensive research. This error typically occurs if ProGuard doesn't have the complete class hierarchy of all classes that are processed. Have you suppressed any warnings with
-dontwarn
or-ignorewarnings
? Can you run ProGuard without these settings? If you get warnings about missing classes, can you add their jars to the input?See https://www.guardsquare.com/en/products/proguard/manual/troubleshooting#superclass
Closing this issue.
Please also note that when using ProGuard for an android project, there is no need for preverification, so you should add -dontpreverify in your configuration which probably also avoid the problem.