Usage

To run ProGuard, just type:

java -jar proguard.jar options ...

Or, assuming the ProGuard jar is in your class path:

java proguard.ProGuard options ...

Options can also be put in one or more configuration files. Typically, you'll put most options in a configuration file, and just call:

java -jar proguard.jar @myconfig.pro

where myconfig.pro contains the actual options.

You can simply combine command line options and options from configuration files, e.g.:

java -jar proguard.jar @myconfig.pro -printusage -printmapping

In a configuration file, a # sign and all remaining characters on that line are ignored, allowing you to add comments.

Extra whitespace between words and delimiters is ignored. To specify file names with spaces or special characters, or more exotically, to specify empty class names, words can be quoted with single or double quotes. Note that the quotes may need to be escaped when used on the command line, to avoid gobbling by the shell.

Options can be grouped arbitrarily in arguments on the command line and in lines in configuration files. This means that you can quote any arbitrary section of command line options, to avoid shell expansion of special characters, for instance.

The order of the options is irrelevant. They can be abbreviated to their first unique characters.

 
Options

The following table lists all ProGuard options:

@filename

Short for '-include filename'.

-include filename

Recursively reads configuration commands from the given file filename.

-libraryjars jarname[:...]

Specifies the library jars of the application to be processed. The class files in these jars will not be included in the output jar. The specified library jars should at least contain the class files that are extended by application class files. Library class files that are only called needn't be present. The jars can be specified with one or more -libraryjars directives. Multiple jars can also be specified using the path separator (e.g. ':' on Unix, or ';' on Windows platforms).

Please note that the boot path and class path set for running ProGuard are not considered when looking for library classes. This also means that you explicitly have to specify the run-time jar that your code will use. Although seemingly cumbersome, it allows you to process applications targeted at different run-time environments. For example, you can process J2SE applications as well as J2ME midlets, just by specifying the appropriate run-time jar.

-injars jarname[:...]

Specifies the program jars of the application to be processed. The class files in these jars will be processed and merged in the output jar. Any non-class files will simply be copied. The jars can be specified with one or more -injars directives. Multiple jars can also be specified using the path separator (e.g. ':' on Unix, or ';' on Windows platforms).

-outjar jarname

Specifies the name of the output jar. It must be different from the input jars. Without this directive, no jars will be written.

-keep class_specification

Specifies classes and class members (fields and methods) to be preserved. They will be preserved with their original names. This is typically the required seed for recursively determining which other classes and class members need to be preserved. For example, in order to keep an application, you can specify the main class along with its main method. In order to process a library, you should specify all publicly accessible items.

-keepclassmembers class_specification

Specifies class members to be preserved, if their classes are preserved as well. For example, you may want to keep all serialization fields and methods of classes that implement the Serializable interface.

-keepclasseswithmembers class_specification

Specifies classes and class members to be preserved, on the condition that all of the specified class members are present. For example, you may want to keep all applications that have a main method, without having to list them explicitly.

-keepnames class_specification

Specifies classes and class members whose names are to be preserved, if they aren't removed in the shrinking phase. For example, you may want to keep all class names of classes that implement the Serializable interface, so that the processed code remains compatible with any originally serialized classes. Classes that aren't used at all can still be removed.

-keepclassmembernames class_specification

Specifies class members whose names are to be preserved, if they aren't removed in the shrinking phase. For example, you may want to preserve the name of the synthetic class$ methods when processing a library, so ProGuard can detect it again when processing an application that uses the processed library.

-keepclasseswithmembernames class_specification

Specifies classes and class members whose names are to be preserved, on the condition that all of the specified class members are present after the shrinking phase. For example, you may want to keep all native method names and the names of their classes, so that the processed code can still link with the native library code. Native methods that aren't used at all can still be removed. If a class file is used, but none of its native methods are, its name will still be obfuscated.

-keepattributes [attribute_name,...]

Specifies any optional attributes to be preserved. The attributes can be specified with one or more -keepattributes directives. Multiple attributes can also be specified separated by commas. An empty list or a * wildcard preserves all attributes. Typical optional attributes are LineNumberTable, LocalVariableTable, SourceFile, Deprecated, and Synthetic. The InnerClasses attribute name can be specified as well, referring to the source name part of this attribute. For example, you could keep the Deprecated attribute when processing a library. Only applicable when obfuscating.

-renamesourcefileattribute [string]

Specifies a constant string to be put in the SourceFile attributes of the class files. Note that the attribute also has to be preserved explicitly using the -keepattributes directive, or it will be removed anyway. For example, you may want to have your processed libraries and applications produce useful obfuscated stack traces. Only applicable when obfuscating.

-printseeds [filename]

Specifies to exhaustively list classes and class members matched by the various -keep commands. The list is printed to the standard output or to the given file. The list can be useful to verify if the intended class members are really found, especially if you're using wildcards. For example, you may want to list all the applications or all the applets that you are keeping.

-printusage [filename]

Specifies to list dead code of the input class files. The list is printed to the standard output or to the given file. For example, you can list the unused code of an application. Only applicable when shrinking.

-printmapping [filename]

Specifies to print the mapping from old names to new names for classes and class members that have been renamed. The mapping is printed to the standard output or to the given file. It is required if you ever want to make sense again of obfuscated stack traces. Only applicable when obfuscating.

-verbose

Specifies to write out some more information during processing. If the program terminates with an exception, this option will print out the entire stack trace, instead of just the exception message.

-dump [filename]

Specifies to write out the internal structure of the class files, after any processing. The structure is printed to the standard output or to the given file. For example, you may want to write out the contents of a given jar file, without shrinking or obfuscating it first.

-ignorewarnings

Specifies to print any warnings about unresolved references to superclasses, interfaces, or class members, but to continue processing in any case. If the classes or class members are indeed required for processing, the output jar will not function properly. Only use this option if you know what you're doing!

-dontwarn

Specifies not to warn about unresolved references at all. Again, if the unresolved classes or class members are indeed required for processing, the output jar will not function properly. Only use this option if you know what you're doing!

-dontnote

Specifies not to print notes about class casts of variable dynamically created objects. These notes provide hints about classes that may have to be kept.

-dontshrink

Specifies not to shrink the input class files. By default, shrinking is applied: all classes and class members are removed, except for the ones listed by the various -keep commands, and the ones they depend on, recursively.

-dontobfuscate

Specifies not to obfuscate the input class files. By default, obfuscation is applied: classes and class members receive new short random names, except for the ones listed by the various -keep commands. Internal attributes that are useful for debugging, such as source files names, variable names, and line numbers are removed.

-dontusemixedcaseclassnames

Specifies not to generate mixed-case class names while obfuscating. By default, obfuscated class names can contain a mix of upper-case characters and lower-case characters. This creates perfectly acceptable and usable jars. Only if a jar is unpacked on a platform with a case-insensitive filing system (say, Windows), the unpacking tool may let similarly named class files overwrite each other. Code that self-destructs when it's unpacked! Developers who really want to unpack their jars on Windows and who are unable to switch to another development platform can use this option to switch off this behavior. Note that the obfuscated jars will become larger as a result. Only applicable when obfuscating.

-overloadaggressively

Specifies to apply aggressive overloading while obfuscating. Multiple fields and methods can then get the same names, as long as their arguments and return types are different (not just their arguments, in the case of methods). This option can make the output jar even smaller (and less comprehensible). Only applicable when obfuscating.

Note that the resulting class files fall within the Java bytecode specification (cfr. The Java Virtual Machine Specification, Second Edition, first paragraphs of Section 4.5 and Section 4.6), even though this kind of overloading is not allowed in the Java language (cfr. The Java Language Specification, Second Edition, Section 8.3 and Section 8.4.7). Still, some tools have problems with it. Most notably, Sun's JDK 1.2.2 javac compiler produces an exception when compiling with such a library (cfr. Bug #4216736). You therefore probably shouldn't use this option for processing libraries.

-defaultpackage [package_name]

Specifies to repackage all class files that are renamed into the single given package. Without argument or with an empty string (''), the package is removed completely. This option can make the output jar even smaller (and less comprehensible). Only applicable when obfuscating.

Note that this kind of repackaging may cause access permissions to become inconsistent, e.g. a class with default access may move to a different package from some other class that is using it. This may seem unusual, but it is formally allowed by Java's binary compatibility specifications (cfr. The Java Language Specification, Second Edition, Section 13.4.6).

Counter-indications: users have reported problems using this option in the circumstances listed below. Some environments don't seem to follow the compatibility specifications and strictly enforce access permissions.

When in doubt, just leave the packaging untouched by not using this option.

-dontskipnonpubliclibraryclasses

Specifies not to ignore non-public library classes. By default, non-public library classes are skipped while parsing library jars. The classes are typically not relevant during processing, since they don't affect the actual program code in the input jars. Ignoring them reduces memory usage and processing time. Occasionally, a badly designed library may contain a non-public library class that is extended/implemented by a public library class. If the latter library class in turn is extended/implemented by a program class, ProGuard will complain that it can't find the non-public library class, which it had ignored during parsing. This option will overcome that problem, at the cost of greater memory usage and longer processing time.

 
-keep Options

The various -keep options may seem a bit confusing at first, but there's actually a pattern behind them. The following table summarizes how they are related:

Keep From shrinking & obfuscation From obfuscation only
Classes and class members -keep -keepnames
Class members only -keepclassmembers -keepclassmembernames
Classes and class members, if class members present -keepclasseswithmembers -keepclasseswithmembernames

Each -keep option is of course followed by a specification of the classes and class members to which it should be applied.

 
File Names

In a ProGuard configuration, file names and jar names can be specified using absolute or relative paths.

The names can contain Java system properties delimited by '<' and '>'. The system properties are automatically replaced by their respective values.

For example, <java.home>/lib/rt.jar will automatically be expanded to something like /usr/local/java/jdk/jre/lib/rt.jar.

Names with special characters like spaces and parentheses should be quoted with single or double quotes. Note that each file name in a list of names has to be quoted individually. Also note that the quotes may need to be escaped when used on the command line, to avoid gobbling by the shell.

For example, on the command line, you could use an option like '-injars "my program.jar":"/your directory/your program.jar"'.

 
Class Specifications

A class specification is a template of classes and class members (fields and methods). It is used in the various -keep options. The corresponding option is only applied to classes and class members that match the template.

The template was designed to look very Java-like, with some extensions for wildcards. To get a feel for the syntax, you should probably look at the examples, but this is an attempt at a complete formal definition:

[[!]public|final|abstract ...] ([!]interface)|class classname
    [extends|implements classname]
[{
    [[!]public|private|protected|static|volatile|transient ...] <fields> |
                                                                (fieldtype fieldname);
    [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |
                                                                                   <init>(argumenttype,...) |
                                                                                   classname(argumenttype,...) |
                                                                                   (returntype methodname(argumenttype,...));
    [[!]public|private|protected|static ... ] *;
    ...
}]

Square brackets "[]" mean that something is optional. Ellipsis dots "..." mean that any number of items may be specified. A vertical bar "|" indicates a choice between alternatives. Non-bold parentheses "()" just group parts of the specification that belong together. The indentation tries to clarify the intended meaning, but white-space is irrelevant in actual configuration files.


Copyright © 2002 Eric Lafortune.