Products
Products
Open-source Technology
Solutions
Resources
Company
While preparing a configuration for processing your code, you may bump into a few problems. The following sections discuss some common issues and solutions:
ProGuard may print out some notes and non-fatal warnings:
(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..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.class.getAnnotations()
". You then generally need to preserve optional class file attributes, which ProGuard removes by default. The attributes contain information about annotations, enclosing classes, enclosing methods, etc. In a summary in the log, ProGuard provides a suggested configuration, like -keepattributes *Annotation*
. If you're sure the attributes are not necessary, you can switch off these notes by specifying the -dontnote
option.-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 automatically keep such descriptor classes with the -keep
option modifier includedescriptorclasses
(-keep,includedescriptorclasses
...). You can switch off these notes by specifying the -dontnote
option.-keep
option to preserve the given library class. However, you don't need to keep any library classes. ProGuard always leaves underlying libraries unchanged. You can switch off these notes by specifying the -dontnote
option.-keepclassmembers
/-keepclasseswithmembers
option to preserve fields or methods in the given class, but it doesn't specify which fields or methods. This way, the option simply won't have any effect. You probably want to specify one or more fields or methods, as usual between curly braces. You can specify all fields or methods with a wildcard "*;
". You should also consider if you just need the more common -keep
option, which preserves all specified classes and class members. The overview of all keep
options can help. You can switch off these notes by specifying the -dontnote
option.-assumenosideeffects
to indicate that the specified methods don't have any side effects. However, the configuration tries to match all methods, by using a wildcard like "*;
". This includes methods from java.lang.Object
, such as wait()
and notify()
. Removing invocations of those methods will most likely break your application. You should list the methods without side effects more conservatively. You can switch off these notes by specifying the -dontnote
option.-dontnote
option.ProGuard may terminate when it encounters parsing errors or I/O errors, or some more serious warnings:
A class in one of your program jars or library jars is referring to a class or interface that is missing from the input. The warning lists both the referencing class(es) and the missing referenced class(es). There can be a few reasons, with their own solutions:
If the missing class is referenced from your own code, you may have forgotten to specify an essential library. Just like when compiling all code from scratch, you must specify all libraries that the code is referencing, directly or indirectly. If the library should be processed and included in the output, you should specify it with -injars
, otherwise you should specify it with -libraryjars
. For example, if ProGuard complains that it can't find a java.lang
class, you have to make sure that you are specifying the run-time library of your platform. For JSE, these are typically packaged in lib/rt.jar
(vm.jar
for IBM's JVM, and classes.jar
in MacOS X) or as of Java 9, jmods/java.base.jmod
.
If the missing class is referenced from a pre-compiled third-party library, and your original code runs fine without it, then the missing dependency doesn't seem to hurt. The cleanest solution is to filter out the referencing class or classes from the input, with a filter like "-injars myapplication.jar(!somepackage/SomeUnusedReferencingClass.class)
". DexGuard will then skip this class entirely in the input, and it will not bump into the problem of its missing reference. However, you may then have to filter out other classes that are in turn referencing the removed class. In practice, this works best if you can filter out entire unused packages at once, with a wildcard filter like "-libraryjars mylibrary.jar(!someunusedpackage/**)
".
If you don't feel like filtering out the problematic classes, you can try your luck with the -ignorewarnings
option, or even the -dontwarn
option. Only use these options if you really know what you're doing though.
-ignorewarnings
or -dontwarn
, but it didn't work out. ProGuard's optimization step and preverification step really need the missing classes to make sense of the code. Preferably, you would solve the problem by adding the missing library, as discussed. If you're sure the class that references the missing class isn't used either, you could also try filtering it out from the input, by adding a filter to the corresponding -injars
option: "-injars myapplication.jar(!somepackage/SomeUnusedClass.class)
". As a final solution, you could switch off optimization (-dontoptimize
) and preverification (-dontpreverify
).A program class is referring to a field or a method that is missing from a library class. The warning lists both the referencing class and the missing referenced class member. Your compiled class files are inconsistent with the libraries. You may need to recompile the class files, or otherwise upgrade the libraries to consistent versions.
If there are unresolved references to class members in program classes, your compiled 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 compiled class files and rebuilding your project.
If there are unresolved references to class members in library classes, your compiled class files are inconsistent with the libraries. You may need to recompile the class files, or otherwise upgrade the libraries to consistent versions.
Alternatively, you may get away with ignoring the inconsistency with the options -ignorewarnings
or even -dontwarn
.
-injars
) and library code (specified with -libraryjars
), and try again.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.-keep
option and the mapping file specified with an -applymapping
option, 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.-applymapping
option, 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.-keep
options-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.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
.
As of Java 9, the runtime classes are packaged in <java.home>/jmods/java.base.jmod
and other modules next to it.
-DsuppressSwingDropSupport=true
when running the GUI.Should ProGuard crash while processing your application:
You can try increasing the heap size of the Java virtual machine, with the usual -Xmx
option:
java -Xmx1024m
ANT_OPTS=-Xmx1024m
GRADLE_OPTS=-Xmx1024m
MAVEN_OPTS=-Xmx1024m
-Xmx1024m
to the file eclipse.ini
inside your Eclipse install.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.
-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.-dontoptimize
option. In any case, please report the problem, preferably with the simplest example that causes ProGuard to crash.If ProGuard seems to run fine, but your processed code doesn't look right, there might be a couple of reasons:
-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.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, with an option like "-keep interface MyMarkerInterface
".
Similarly, if you are keeping classes based on annotations, you may have to avoid that the annotation classes themselves are removed in the shrinking step. You should package the annotation classes as a library, or explicitly keep them in your program code with an option like "-keep @interface *
".
-keep
option is preserving the original names. These options may be hiding in your own configuration files or in configuration files from libraries.-keep
options preserving the original names, for the sake of libraries like GSON. Such libraries perform reflection on the fields. If the names were obfuscated, the resulting JSON strings would come out obfuscated as well, which generally breaks persistence of the data or communication with servers.LocalVariableTable
or LocalVariableTypeTable
attributes.If ProGuard seems to run fine, but the external preverifier subsequently produces errors, it's usually for a single reason:
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.
If ProGuard runs fine, but your processed application doesn't work, there might be several reasons:
Class.forName
, trying to create the missing class dynamically. ProGuard can only detect constant name arguments, like Class.forName("com.example.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 com.example.MyClass
" or "-keep class * implements com.example.MyInterface
". While setting up your configuration, you can specify the option -addconfigurationdebugging
to help track down these cases at run-time and let the instrumented code suggest settings for them.myClass.getField
, trying to find some field dynamically. Since ProGuard can't always detect this automatically, you have to keep the missing field using the appropriate -keep
option, e.g. "-keepclassmembers class com.example.MyClass { int myField; }
". While setting up your configuration, you can specify the option -addconfigurationdebugging
to help track down these cases at run-time and let the instrumented code suggest settings for them.myClass.getMethod
, trying to find some method dynamically. Since ProGuard can't always detect this automatically, you have to keep the missing method using the appropriate -keep
option, e.g. "-keepclassmembers class com.example.MyClass { void myMethod(); }
". While setting up your configuration, you can specify the option -addconfigurationdebugging
to help track down these cases at run-time and let the instrumented code suggest settings for them. More specifically, if the method reported as missing is values
or valueOf
, you probably have to keep some methods related to enumerations.-adaptresourcefilenames
and/or -adaptresourcefilecontents
. Furthermore, directory entries in jar files aren't copied, unless you specify the option -keepdirectories
. Note that Sun advises against calling Class.getResource()
for directories (Sun Bug #4761949](http://bugs.sun.com/view_bug.do?bug_id=4761949)).-keepattributes *Annotation*
.-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,META-INF/INDEX.LIST
, listing all class files in the jar. ProGuard by default copies files like these unchanged. ProGuard may however remove or rename classes, thus invalidating the file. You should filter the index file out of the input (-injars in.jar(!META-INF/INDEX.LIST)
) or update the file after having applied ProGuard (jar -i out.jar
).-microedition
option, so the processed class files are preverified properly.-repackageclasses ''
and -overloadaggressively
.-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.volatile
. If this is not possible for some reason, you'll have to switch off optimization using the -dontoptimize
option.-overloadaggressively
option. The class java.lang.reflect.Proxy
can't handle classes that contain methods with the same names and signatures, but different return types. Its method newProxyInstance
then throws this exception. You can avoid the problem by not using the option.-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.-overloadaggressively
option. You should then use the same option again in the second processing round.LocalVariableTable
or LocalVariableTypeTable
attributes, ProGuard's optimizing step is sometimes unable to update them consistently. You should then let the obfuscation step remove these attributes or disable the optimization step.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.
-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.