Troubleshooting

While preparing a configuration for processing your code, you may bump into a few problems. The following sections discuss some common issues and solutions:

Problems while processing

Unexpected observations after processing

Problems while preverifying for Java Micro Edition

Problems at run-time

 

Problems while processing

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.
Note: the configuration keeps the entry point '...', but not the descriptor class '...'
Your configuration contains a -keep option to preserve the given method (or field), but no -keep option for the given class that is an argument type or return type in the method's descriptor. You may then want to keep the class too. Otherwise, ProGuard will obfuscate its name, thus changing the method's signature. The method might then become unfindable as an entry point, e.g. if it is part of a public API. You can switch off these notes by specifying the -dontnote option.
Note: duplicate definition of program/library class
Your program jars or library jars contain multiple definitions of the listed classes. ProGuard continues processing as usual, only considering the first definitions. The warning may be an indication of some problem though, so it's advisable to remove the duplicates. A convenient way to do so is by specifying filters on the input jars or library jars. You can switch off these notes by specifying the -dontnote option.
Warning: can't write resource ... Duplicate zip entry
Your input jars contain multiple resource files with the same name. ProGuard continues copying the resource files as usual, skipping any files with previously used names. Once more, the warning may be an indication of some problem though, so it's advisable to remove the duplicates. A convenient way to do so is by specifying filters on the input jars. There is no option to switch off these warnings.

ProGuard may terminate when it encounters parsing errors or I/O errors, or some more serious warnings:

Warning: can't find superclass or interface
If there are unresolved references to superclasses or interfaces, you most likely forgot to specify an essential library. All libraries that are referenced by your code should be specified, including the Java run-time library. For specifying libraries, use the -libraryjars option.

If the class that is reported as missing is a non-public library class, you should specify the -dontskipnonpubliclibraryclasses option. A common example is the class java.util.zip.ZipConstants, which is used as an interface class in some public classes, even though it is only package visible (in this case, the warning could also be ignored, because the class is not a fundamental part of the class hierarchy).

If you're missing a library and you're absolutely sure it isn't used anyway, you can try your luck with the -ignorewarnings option, or even the -dontwarn option.

Warning: can't find referenced field/method
If there are unresolved references to class members in input classes, your class files are most likely inconsistent. Possibly, some class file didn't get recompiled properly, or some class file was left behind after its source file was removed. Try removing all class files, recompiling them, zipping them up, and running ProGuard again.

If the class member that is reported as missing is actually implemented in a non-public library class, you should specify the -dontskipnonpubliclibraryclasses option. A common example is the method setLength(int) in the public class java.lang.StringBuilder. This method is actually defined in the package visible superclass java.lang.AbstractStringBuilder, which ProGuard ignores by default.

If your program classes reside in the same packages as library classes, and refer to their package visible class members, then you should specify the -dontskipnonpubliclibraryclassmembers option.

Warning: can't find enclosing class/method
If there are unresolved references to classes that are defined inside methods in your input, once more, your class files are most likely inconsistent. Possibly, some class file didn't get recompiled properly, or some class file was left behind after its source file was removed. Try removing all class files, recompiling them, zipping them up, and running ProGuard again.
Warning: library class ... depends on program class ...
If any of your library classes depend on your program classes, by extending, implementing or just referencing them, your processed code will generally be unusable. Program classes can depend on library classes, but not the other way around. Program classes are processed, while library classes always remain unchanged. It is therefore impossible to adapt references from library classes to program classes, for instance if the program classes are renamed. You should define a clean separation between program code and library code, and try again.
Warning: class file ... unexpectedly contains class ...
The given class file contains a definition for the given class, but the directory name of the file doesn't correspond to the package name of the class. ProGuard will accept the class definition, but the current implementation will not write out the processed version. Please make sure your input classes are packaged correctly. Notably, class files that are in the WEB-INF/classes directory in a war should be packaged in a jar and put in the WEB-INF/lib directory. If you don't mind these classes not being written to the output, you can specify the -ignorewarnings option, or even the -dontwarn option.
Warning: ... is not being kept as ..., but remapped to ...
There is a conflict between a -keep option in the configuration, and the mapping file, in the obfuscation step. The given class name or class member name can't be kept by its original name, as specified in the configuration, but it has to be mapped to the other given name, as specified in the mapping file. You should adapt your configuration or your mapping file to remove the conflict. Alternatively, if you're sure the renaming won't hurt, you can specify the -ignorewarnings option, or even the -dontwarn option.
Warning: field/method ... can't be mapped to ...
There is a conflict between some new program code and the mapping file, in the obfuscation step. The given class member can't be mapped to the given name, because it would conflict with another class member that is already being mapped to the same name. This can happen if you are performing incremental obfuscation, applying an obfuscation mapping file from an initial obfuscation step. For instance, some new class may have been added that extends two existing classes, introducing a conflict in the name space of its class members. If you're sure the class member receiving another name than the one specified won't hurt, you can specify the -ignorewarnings option, or even the -dontwarn option. Note that you should always use the -useuniqueclassmembernames option in the initial obfuscation step, in order to reduce the risk of conflicts.
Error: You have to specify '-keep' options
You either forgot to specify -keep options, or you mistyped the class names. ProGuard has to know exactly what you want to keep: an application, an applet, a servlet, a midlet,..., or any combination of these. Without the proper seed specifications, ProGuard would shrink, optimize, or obfuscate all class files away.
Error: Expecting class path separator ';' before 'Files\Java\...' (in Windows)
If the path of your run-time jar contains spaces, like in "Program Files", you have to enclose it with single or double quotes, as explained in the section on file names. This is actually true for all file names containing special characters, on all platforms.
Error: Can't read [.../lib/rt.jar] (No such file or directory) (in MacOS X)
In MacOS X, the run-time classes may be in a different place than on most other platforms. You'll then have to adapt your configuration, replacing the path <java.home>/lib/rt.jar by <java.home>/../Classes/classes.jar.

Should ProGuard crash while processing your application:

OutOfMemoryError
You can try increasing the heap size of the Java virtual machine (with the usual -Xms and -Xmx options). You can also reduce the amount of memory that ProGuard needs by removing unnecessary library jars from your configuration, or by filtering out unused library packages and classes. Remember that only classes or interfaces that are extended or implemented by classes in your input jars are required.
StackOverflowError
This error might occur when processing a large code base on Windows (surprisingly, not so easily on Linux). In theory, increasing the stack size of the Java virtual machine (with the usual -Xss option) should help too. In practice however, the -Xss setting doesn't have any effect on the main thread, due to Sun Bug #4362291. As a result, this solution will only work when running ProGuard in a different thread, e.g. from its GUI.
Unexpected error
ProGuard has encountered an unexpected condition, typically in the optimization step. It may or may not recover. You should be able to avoid it using the -dontoptimize option. In any case, please report the problem, preferably with the simplest example that causes ProGuard to crash.
Otherwise...
Maybe your class files are corrupt. See if recompiling them and trying again helps. If not, please report the problem, preferably with the simplest example that causes ProGuard to crash.

 

Unexpected observations after processing

If ProGuard seems to run fine, but your processed code doesn't look right, there might be a couple of reasons:
Disappearing classes
If you are working on Windows and it looks like some classes have disappeared from your output, you should make sure you're not writing your output class files to a directory (or unpacking the output jar). On platforms with case-insensitive file systems, such as Windows, unpacking tools often let class files with similar lower-case and upper-case names overwrite each other. If you really can't switch to a different operating system, you could consider using ProGuard's -dontusemixedcaseclassnames option.

Also, you should make sure your class files are in directories that correspond to their package names. ProGuard will read misplaced class files, but it will currently not write their processed versions. Notably, class files that are in the WEB-INF/classes directory in a war should be packaged in a jar and put in the WEB-INF/lib directory.

Classes or class members not being kept
If ProGuard is not keeping the right classes or class members, make sure you are using fully qualified class names. If the package name of some class is missing, ProGuard won't match the elements that you might be expecting. It may help to double-check for typos too. You can use the -printseeds option to see which elements are being kept exactly.

If you are using marker interfaces to keep other classes, the marker interfaces themselves are probably being removed in the shrinking step. You should therefore always explicitly keep any marker interfaces.

Variable names not being obfuscated
If the names of the local variables and parameters in your obfuscated code don't look obfuscated, because they suspiciously resemble the names of their types, it's probably because the decompiler that you are using is coming up with those names. ProGuard's obfuscation step does remove the original names entirely, unless you explicitly keep the LocalVariableTable or LocalVariableTypeTable attributes.
 

Problems while preverifying for Java Micro Edition

If ProGuard seems to run fine, but the external preverifier subsequently produces errors, it's usually for a single reason:
InvalidClassException, class loading error, or verification error
If you get any such message from the preverifier, you are probably working on a platform with a case-insensitive file system, such as Windows. The preverify tool always unpacks the jars, so class files with similar lower-case and upper-case names overwrite each other. You can use ProGuard's -dontusemixedcaseclassnames option to work around this problem.

If the above doesn't help, there is probably a bug in the optimization step of ProGuard. Make sure you are using the latest version. You should be able to work around the problem by using the -dontoptimize option. You can check the bug database to see if it is a known problem (often with a fix). Otherwise, please report it, preferably with the simplest example on which you can find ProGuard to fail.

Note that it is no longer necessary to use an external preverifier. With the -microedition option, ProGuard will preverify the class files for Java Micro Edition.

 

Problems at run-time

If ProGuard runs fine, but your processed application doesn't work, there might be several reasons:
Stack traces without class names or line numbers
If your stack traces don't contain any class names or lines numbers, even though you are keeping the proper attributes, make sure this debugging information is present in your compiled code to start with. Notably the Ant javac task has debugging information switched off by default.
NoClassDefFoundError
Your class path is probably incorrect. It should at least contain all library jars and, of course, your processed program jar.
ClassNotFoundException
Your code is probably calling Class.forName, trying to create the missing class dynamically. ProGuard can only detect constant name arguments, like Class.forName("mypackage.MyClass"). For variable name arguments like Class.forName(someClass), you have to keep all possible classes using the appropriate -keep option, e.g. "-keep class mypackage.MyClass" or "-keep class * implements mypackage.MyInterface".
NoSuchMethodException
Your code is probably calling something like myClass.getMethod, trying to find some method dynamically. Since ProGuard isn't detecting this (yet), you have to keep the missing method in using the appropriate -keep option, e.g. "-keep class mypackage.MyClass { void myMethod(); }".
MissingResourceException or NullPointerException
Your processed code may be unable to find some resource files. ProGuard simply copies resource files over from the input jars to the output jars. Their names and contents remain unchanged, unless you specify the options -adaptresourcefilenames and/or -adaptresourcefilecontents.

Note that directory entries in jar files aren't copied at all. If you refer to any directories from your code, you should add them manually.

Invalid or corrupt jarfile
You are probably starting your application with the java option -jar instead of the option -classpath. The java virtual machine returns with this error message if your jar doesn't contain a manifest file (META-INF/MANIFEST.MF), if the manifest file doesn't specify a main class (Main-Class: ...), or if the jar doesn't contain this main class. You should then make sure that the input jar contains a valid manifest file to start with, that this manifest file is the one that is copied (the first manifest file that is encountered), and that the main class is kept in your configuration,
InvalidClassException, class loading error, or verification error (in Java Micro Edition)
If you get such an error in Java Micro Edition, you may have forgotten to specify the -microedition option, so the processed class files are preverified properly.
Error: No Such Field or Method, Error verifying method (in a Java Micro Edition emulator)
If you get such a message in a Motorola or Sony Ericsson phone emulator, it's because these emulators don't like packageless classes and/or overloaded fields and methods. You can work around it by not using the options -repackageclasses '' and -overloadaggressively. If you're using the JME WTK plugin, you can adapt the configuration proguard/wtk/default.pro that's inside the proguard.jar.
Failing midlets (on a Java Micro Edition device)
If your midlet runs in an emulator and on some devices, but not on some other devices, this is probably due to a bug in the latter devices. For some older Motorola and Nokia phones, you might try specifying the -useuniqueclassmembernames option. It avoids overloading class member names, which triggers a bug in their java virtual machine.

You might also try using the -dontusemixedcaseclassnames option. Even if the midlet has been properly processed and then preverified on a case-sensitive file system, the device itself might not like the mixed-case class names. Notably, the Nokia N-Gage emulator works fine, but the actual device seems to exhibit this problem.

Disappearing loops
If your code contains empty busy-waiting loops, ProGuard's optimization step may remove them. More specifically, this happens if a loop continuously checks the value of a non-volatile field that is changed in a different thread. The specifications of the Java Virtual Machine require that you always mark fields that are accessed across different threads without further synchronization as volatile. If this is not possible for some reason, you'll have to switch off optimization using the -dontoptimize option.
SecurityException: SHA1 digest error
You may have forgotten to sign your program jar after having processed it with ProGuard.
ClassCastException: class not an enum, or
IllegalArgumentException: class not an enum type
You should make sure you're preserving the special methods of enumeration types, which the run-time environment calls by introspection. The required options are shown in the examples.
ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy
You are probably processing annotations involving enumerations. Again, you should make sure you're preserving the special methods of the enumeration type, as shown in the examples.
CompilerError: duplicate addition
You are probably compiling or running some code that has been obfuscated with the -overloadaggressively option. This option triggers a bug in sun.tools.java.MethodSet.add in Sun's JDK 1.2.2, which is used for (dynamic) compilation. You should then avoid this option.
ClassFormatError: repetitive field name/signature
You are probably processing some code that has been obfuscated before with the -overloadaggressively option. You should then use the same option again in the second processing round.
NoSuchMethodError or AbstractMethodError
You should make sure you're not writing your output class files to a directory on a platform with a case-insensitive file system, such as Windows. Please refer to the section about disappearing classes for details.

Furthermore, you should check whether you have specified your program jars and library jars properly. Program classes can refer to library classes, but not the other way around.

If all of this seems ok, perhaps there's a bug in ProGuard (gasp!). If so, please report it, preferably with the simplest example on which you can find ProGuard to fail.

VerifyError
Verification errors when executing a program are almost certainly the result of a bug in the optimization step of ProGuard. Make sure you are using the latest version. You should be able to work around the problem by using the -dontoptimize option. You can check the bug database to see if it is a known problem (often with a fix). Otherwise, please report it, preferably with the simplest example on which ProGuard fails.

Copyright © 2002-2008 Eric Lafortune.