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
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With