Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard - Can't find common super class / java.lang.VerifyError

Tags:

java

proguard

We are developing a desktop application. When running ProGuard (version 5.3.3) on the code using the following configuration flags:

-dontoptimize
-allowaccessmodification
-dontusemixedcaseclassnames
-dontwarn

Proguard gives the following error:

Unexpected error while performing partial evaluation:
  Class       = [com/code/backend/e/b/b]
  Method      = [b(Ljava/lang/String;)Ljava/nio/file/Path;]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes))
Unexpected error while preverifying:
  Class       = [com/code/backend/e/b/b]
  Method      = [b(Ljava/lang/String;)Ljava/nio/file/Path;]
  Exception   = [java.lang.IllegalArgumentException] (Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes))


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task 'proguard'.
> Can't find common super class of [com/google/common/collect/ImmutableList] (with 2 known super classes) and [com/google/common/collect/UnmodifiableIterator] (with 1 known super classes)

If the flag -dontpreverify is added to the configuration the build will succeed. However when running the jar-file we then get the following error:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 11
Exception Details:
  Location:
    com/code/code2/MainWindow.b(Lcom/code/code2/ClientAPIProtos$SoftwareStatus;)V @1: ifnull
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: 2bc6 000a 2ab4 00bc c700 04b1 2bb2 00a4
    0x0000010: a500 0a2b b800 f599 0018 2ab4 00bc b601
    0x0000020: 9299 0020 2ab4 00bc 03b6 0193 a700 152a
    0x0000030: b400 bcb6 0192 9a00 0b2a b400 bc04 b601
    0x0000040: 932b b800 f699 0012 1225 4db8 0138 4e2a
    0x0000050: 04b5 00c8 a700 0f12 1e4d b801 3a4e 2a03
    0x0000060: b500 c82a b400 bcb6 0191 3a04 1904 c600
    0x0000070: 0c2c 1904 b601 799a 000b 2ab4 00bc 2cb6
    0x0000080: 0195 2ab4 00bc b601 903a 0519 05c6 0009
    0x0000090: 2d19 05a5 000b 2ab4 00bc 2db6 0194 b1  

    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Which can be avoided by using the JVM flag -noverify. Reading the thread:

Obfuscation causes VerifyError: Expecting a stackmap frame

We would like to avoid these 'no verification' flags if possible.

Note: The build error occurs even when adding

-dontobfuscate
-dontshrink
like image 717
Erik Dackander Avatar asked Jul 31 '17 09:07

Erik Dackander


3 Answers

You're specifying the option -dontwarn to suppress warnings about unresolved references. This can lead to problems while processing the code. ProGuard needs those references, e.g. in the preverification step. The error indeed suggests that the input doesn't contain all necessary dependencies: some common superclass or interface of ImmutableList and UnmodifiableIterator is missing. For a desktop application, you should check that you're specifying a Java runtime jar with all the necessary classes:

-libraryjars <java.home>/lib/rt.jar

See the ProGuard manual > Troubleshooting > Warning: can't find superclass or interface

like image 56
Eric Lafortune Avatar answered Nov 10 '22 06:11

Eric Lafortune


Initialization, verification, and validation are part of the building project. I believe flag -allowaccessmodification is to allow modification when building the project (i.e. your classes are modified from the original structure). When original class structure gets modified then their stack frames are disturbed. This leads to verification failure. If you want to ignore the verify error then as mentioned you need to use the flag that suspends verification.

like image 2
Mohan Raj Avatar answered Nov 10 '22 06:11

Mohan Raj


Troubleshooting

ProGuard may print out some notes and non-fatal warnings:

Note: can't find dynamically referenced class ProGuard can't find a class or interface that your code is accessing by means of introspection. You should check if you want to add the jar that contains this class.

Note: ... calls '(...)Class.forName(variable).newInstance()' ProGuard lists all class casts of dynamically created class instances, like "(MyClass)Class.forName(variable).newInstance()". Depending on your application, you may need to keep the mentioned classes with an option like -keep class MyClass, or their implementations with an option like -keep class * implements MyClass. You can switch off these notes by specifying the -dontnote option.

Note: ... accesses a field/method '...' dynamically ProGuard lists a number of constructs like ".getField("myField")". Depending on your application, you may need to figure out where the mentioned class members are defined and keep them with an option like -keep class MyClass { MyFieldType myField; }. Otherwise, ProGuard might remove or obfuscate the class members, since it can't know which ones they are exactly. It does list possible candidates, for your information. You can switch off these notes by specifying the -dontnote option.

like image 1
Kondal Avatar answered Nov 10 '22 06:11

Kondal