java -jar proguard.jar options ...
lib directory of the
ProGuard distribution. Alternatively, the bin directory contains
some short Linux and Windows scripts containing this command. Typically, you'll
put most options in a configuration file (say, myconfig.pro), and
just call:
java -jar proguard.jar @myconfig.pro
java -jar proguard.jar @myconfig.pro -verbose
You can add comments in a configuration file, starting with a
# character and continuing until the end of the line.
Extra whitespace between words and delimiters is ignored. File names with spaces or special characters should be quoted with single or double quotes.
Options can be grouped arbitrarily in arguments on the command line and in lines in configuration files. This means that you can quote arbitrary sections of command line options, to avoid shell expansion of special characters, for instance.
The order of the options is generally irrelevant. For quick experiments, you can abbreviate them to their first unique characters.
The sections below provide more details:
Keep Options@filename-include
     filename'.-include
    filename-basedirectory
    directoryname-injars
    class_path-injars options.-outjars
    class_path-injars
    options will be written to the named jars. This allows you to collect the
    contents of groups of input jars into corresponding groups of output jars.
    In addition, the output entries can be filtered, as explained in
    the filters section. Each processed class file
    or resource file is then written to the first output entry with a matching
    filter, within the group of output jars.
    
    You must avoid letting the output files overwrite any input files. For
    better readability, class path entries can be specified using multiple
    -outjars options. Without any -outjars options,
    no jars will be written.
-libraryjars
    class_path-libraryjars options.
    Please note that the boot path and the class path set for running ProGuard are not considered when looking for library classes. This means that you explicitly have to specify the run-time jar that your code will use. Although this may seem cumbersome, it allows you to process applications targeted at different run-time environments. For example, you can process J2SE applications as well as JME midlets or Android apps, just by specifying the appropriate run-time jar.
-skipnonpubliclibraryclasses-dontskipnonpubliclibraryclasses-dontskipnonpubliclibraryclassmembers-keepdirectories
    [directory_filter]mypackage.MyClass.class.getResource("")". You'll then want
    to keep the directory corresponding to the package,
    "-keepdirectories mypackage". If the option is specified
    without a filter, all directories are kept. With a filter, only matching
    directories are kept. For instance,
    "-keepdirectories mydirectory" matches the specified
    directory, "-keepdirectories mydirectory/*" matches its
    immediate subdirectories, and
    "-keepdirectories mydirectory/**" matches all of its
    subdirectories.-target version1.0, 1.1,
    1.2, 1.3, 1.4, 1.5 (or
    just 5), 1.6 (or just 6),
    1.7 (or just 7), or 1.8 (or
    just 8). By default, the version numbers of the class files
    are left unchanged. For example, you may want to
    upgrade class files to Java 6, by
    changing their version numbers and having them preverified. You probably
    shouldn't downgrade the version numbers of class files, since the code
    may contain constructs that are not supported in older versions.-forceprocessing
-keep
    [,modifier,...]
    class_specification-keepclassmembers
    [,modifier,...]
    class_specificationSerializable
    interface.-keepclasseswithmembers
    [,modifier,...]
    class_specification-keepnames
    class_specification-keep,allowshrinking
    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. Only applicable when
    obfuscating.
-keepclassmembernames
    class_specification-keepclassmembers,allowshrinking
    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 compiled by
    JDK 1.2 or older, so obfuscators can detect it again when processing an
    application that uses the processed library (although ProGuard itself
    doesn't need this). Only applicable when obfuscating.
-keepclasseswithmembernames
    class_specification-keepclasseswithmembers,allowshrinking
    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. Only applicable when obfuscating.
-printseeds
    [filename]-keep options. 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.
-dontshrink-keep options, and the ones on which
    they depend, directly or indirectly. A shrinking step is also applied
    after each optimization step, since some optimizations may open the
    possibility to remove more classes and class members.-printusage
    [filename]-whyareyoukeeping
    class_specification-verbose option if specified, the traces
    include full field and method signatures. Only applicable when
    shrinking.
-dontoptimize-optimizations
    optimization_filter-optimizationpasses n-assumenosideeffects
    class_specificationSystem.currentTimeMillis(), so that any idle calls to it will
    be removed. With some care, you can also use the option to
    remove logging code. Note that
    ProGuard applies the option to the entire hierarchy of the specified
    methods. Only applicable when optimizing. In general, making assumptions
    can be dangerous; you can easily break the processed code. Only use
    this option if you know what you're doing!-allowaccessmodification-repackageclasses option).
    Counter-indication: you probably shouldn't use this option when processing code that is to be used as a library, since classes and class members that weren't designed to be public in the API may become public.
-mergeinterfacesaggressivelyCounter-indication: setting this option can reduce the performance of the processed code on some JVMs, since advanced just-in-time compilation tends to favor more interfaces with fewer implementing classes. Worse, some JVMs may not be able to handle the resulting code. Notably:
InternalError when
        encountering more than 256 Miranda methods (interface methods
        without implementations) in a class.
-dontobfuscate-keep options.
    Internal attributes that are useful for debugging, such as source files
    names, variable names, and line numbers are removed.-printmapping
    [filename]-applymapping
    filename-useuniqueclassmembernames
    in both obfuscation runs. Only a single mapping file is allowed. Only
    applicable when obfuscating.-obfuscationdictionary
    filename# sign are ignored. Note that an
    obfuscation dictionary hardly improves the obfuscation. Decent compilers
    can automatically replace them, and the effect can fairly simply be undone
    by obfuscating again with simpler names. The most useful application is
    specifying strings that are typically already present in class files (such
    as 'Code'), thus reducing the class file sizes just a little bit more.
    Only applicable when obfuscating.-classobfuscationdictionary
    filename-obfuscationdictionary.
    Only applicable when obfuscating.-packageobfuscationdictionary
    filename-obfuscationdictionary.
    Only applicable when obfuscating.-overloadaggressivelyCounter-indication: 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, Third Edition, Section 8.3 and Section 8.4.5). Still, some tools have problems with it. Notably:
javac compiler produces an exception when
        compiling with such a library (cfr. Bug #4216736).
        You probably shouldn't use this option for processing libraries.pack200 tool reportedly has problems with
        overloaded class members.java.lang.reflect.Proxy can't handle overloaded
        methods.-useuniqueclassmembernamesFor instance, consider two distinct interfaces containing methods with the same name and signature. Without this option, these methods may get different obfuscated names in a first obfuscation step. If a patch is then added containing a class that implements both interfaces, ProGuard will have to enforce the same method name for both methods in an incremental obfuscation step. The original obfuscated code is changed, in order to keep the resulting code consistent. With this option in the initial obfuscation step, such renaming will never be necessary.
This option is only applicable when obfuscating. In fact, if you are planning on performing incremental obfuscation, you probably want to avoid shrinking and optimization altogether, since these steps could remove or modify parts of your code that are essential for later additions.
-dontusemixedcaseclassnames-keeppackagenames
    [package_filter]-flattenpackagehierarchy
    [package_name]-repackageclasses
    [package_name]-flattenpackagehierarchy
    option. It is another example of further obfuscating package names. It can
    make the processed code even smaller and less comprehensible. Its
    deprecated name is -defaultpackage. Only applicable when
    obfuscating.
    Counter-indication: classes that look for resource files in their package directories will no longer work properly if they are moved elsewhere. When in doubt, just leave the packaging untouched by not using this option.
-keepattributes
    [attribute_filter]-keepattributes directives. The
    optional filter is a comma-separated list
    of attribute names that Java virtual
    machines and ProGuard support. Attribute names can
    contain ?, *, and ** wildcards, and they can be
    preceded by the ! negator. For example, you should at least keep
    the Exceptions, InnerClasses, and
    Signature attributes when
    processing a library. You should also
    keep the SourceFile and LineNumberTable
    attributes for producing useful
    obfuscated stack traces. Finally, you may want
    to keep annotations if your code
    depends on them. Only applicable when obfuscating.-keepparameternamesLocalVariableTable and
    LocalVariableTypeTable. It can be useful when
    processing a library. Some IDEs can
    use the information to assist developers who use the library, for example
    with tool tips or autocompletion. Only applicable when obfuscating.-renamesourcefileattribute
    [string]SourceFile
    attributes (and SourceDir attributes) of the class files.
    Note that the attribute has to be present to start with, so it also has to
    be preserved explicitly using the -keepattributes directive.
    For example, you may want to have your processed libraries and
    applications produce useful obfuscated
    stack traces. Only applicable when obfuscating.-adaptclassstrings
    [class_filter]-adaptresourcefilenames
    [file_filter]-adaptresourcefilecontents
    [file_filter]LANG or the Java system
    property file.encoding. For an example,
    see processing resource files.
    Only applicable when obfuscating.
    Caveat: You probably only want to apply this option to text files, since parsing and adapting binary files as text files can cause unexpected problems. Therefore, make sure that you specify a sufficiently narrow filter.
-dontpreverify-microedition
-verbose-dontnote
    [class_filter]-dontwarn
    [class_filter]-ignorewarnings-printconfiguration
    [filename]-dump
    [filename]
Each input entry can be:
The paths of directly specified class files and resource files is ignored, so class files should generally be part of a jar file, an aar file, a war file, an ear file, a zip file, or a directory. In addition, the paths of class files should not have any additional directory prefixes inside the archives or directories.
Each output entry can be:
When writing output entries, ProGuard will generally package the results in a sensible way, reconstructing the input entries as much as required. Writing everything to an output directory is the most straightforward option: the output directory will contain a complete reconstruction of the input entries. The packaging can be almost arbitrarily complex though: you could process an entire application, packaged in a zip file along with its documentation, writing it out as a zip file again. The Examples section shows a few ways to restructure output archives.
Files and directories can be specified as discussed in the section on file names below.
In addition, ProGuard provides the possibility to filter the class path entries and their contents, based on their full relative file names. Each class path entry can be followed by up to 7 types of file filters between parentheses, separated by semi-colons:
If fewer than 7 filters are specified, they are assumed to be the latter filters. Any empty filters are ignored. More formally, a filtered class path entry looks like this:
classpathentry([[[[[[aarfilter;]apkfilter;]zipfilter;]earfilter;]warfilter;]jarfilter;]filefilter)
Square brackets "[]" mean that their contents are optional.
For example, "rt.jar(java/**.class,javax/**.class)" matches all
class files in the java and javax directories inside
the rt jar.
For example, "input.jar(!**.gif,images/**)" matches all files in
the images directory inside the input jar, except
gif files.
The different filters are applied to all corresponding file types, irrespective of their nesting levels in the input; they are orthogonal.
For example,
"input.war(lib/**.jar,support/**.jar;**.class,**.gif)" only
considers jar files in the lib and support
directories in the input war, not any other jar files. It then
matches all class files and gif files that are encountered.
The filters allow for an almost infinite number of packaging and repackaging possibilities. The Examples section provides a few more examples for filtering input and output.
The names can contain Java system properties (or Ant properties, when using Ant), delimited by angular brackets, '<' and '>'. The properties are automatically replaced by their corresponding values.
For example, <java.home>/lib/rt.jar is automatically
expanded to something like /usr/local/java/jdk/jre/lib/rt.jar.
Similarly, <user.home> is expanded to the user's home
directory, and <user.dir> is expanded to the current
working directory.
Names with special characters like spaces and parentheses must be quoted with single or double quotes. Each file name in a list of names has to be quoted individually. Note that the quotes themselves may need to be escaped when used on the command line, to avoid them being gobbled by the shell.
For example, on the command line, you could use an option like '-injars
"my program.jar":"/your directory/your program.jar"'.
| ? | matches any single character in a file name. | 
| * | matches any part of a filename not containing the directory separator. | 
| ** | matches any part of a filename, possibly containing any number of directory separators. | 
java/**.class,javax/**.class" matches all
class files in the java and javax.
Furthermore, a file name can be preceded by an exclamation mark '!' to exclude the file name from further attempts to match with subsequent file names.
For example, "!**.gif,images/**" matches all files in the
images directory, except gif files.
The Examples section provides a few more examples for filtering input and output.
A filter is a list of comma-separated names that can contain wildcards. Only names that match an item on the list pass the filter. The supported wildcards depend on the type of names for which the filter is being used, but the following wildcards are typical:
| ? | matches any single character in a name. | 
| * | matches any part of a name not containing the package separator or directory separator. | 
| ** | matches any part of a name, possibly containing any number of package separators or directory separators. | 
foo,*bar" matches the name foo and
all names ending with bar.
Furthermore, a name can be preceded by a negating exclamation mark '!' to exclude the name from further attempts to match with subsequent names. So, if a name matches an item in the filter, it is accepted or rejected right away, depending on whether the item has a negator. If the name doesn't match the item, it is tested against the next item, and so on. It if doesn't match any items, it is accepted or rejected, depending on the whether the last item has a negator or not.
For example, "!foobar,*bar" matches all names ending with
bar, except foobar.
Keep Options-keep options for shrinking and obfuscation 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 being removed or renamed | From being renamed | 
|---|---|---|
| Classes and class members | -keep | -keepnames | 
| Class members only | -keepclassmembers | -keepclassmembernames | 
| Classes and class members, if class members present | -keepclasseswithmembers | -keepclasseswithmembernames | 
Each of these -keep options is of course followed by a
specification of the classes and class
members (fields and methods) to which it should be applied.
If you're not sure which option you need, you should probably simply use
-keep. It will make sure the specified classes and class members
are not removed in the shrinking step, and not renamed in the obfuscation step.
 
includedescriptorclassesallowshrinkingallowoptimizationallowobfuscation
-keep options and in the
-assumenosideeffects option. 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:
[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname
    [extends|implements [@annotationtype] classname]
[{
    [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> |
                                                                      (fieldtype fieldname);
    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |
                                                                                           <init>(argumenttype,...) |
                                                                                           classname(argumenttype,...) |
                                                                                           (returntype methodname(argumenttype,...));
    [@annotationtype] [[!]public|private|protected|static ... ] *;
    ...
}]
Square brackets "[]" mean that their contents are optional. Ellipsis dots "..." mean that any number of the preceding items may be specified. A vertical bar "|" delimits two 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.
class keyword refers to any interface or class.
    The interface keyword restricts matches to interface
    classes. The enum keyword restricts matches to
    enumeration classes. Preceding the interface or
    enum keywords by a ! restricts
    matches to classes that are not interfaces or enumerations,
    respectively.java.lang.String. Inner classes are separated by a dollar sign
    "$", e.g. java.lang.Thread$State. Class names
    may be specified as regular
    expressions containing the following wildcards:
| ? | matches any single character in a class name, but not the package
    separator. For example, " mypackage.Test?" matches
    "mypackage.Test1" and "mypackage.Test2", but not
    "mypackage.Test12". | 
| * | matches any part of a class name not containing the package separator. For
    example, " mypackage.*Test*" matches
    "mypackage.Test" and
    "mypackage.YourTestApplication", but not
    "mypackage.mysubpackage.MyTest". Or, more generally,
    "mypackage.*" matches all classes in
    "mypackage", but not in its subpackages. | 
| ** | matches any part of a class name, possibly containing any number of
    package separators. For example, " **.Test" matches allTestclasses in all packages except the root package. Or,
    "mypackage.**" matches all classes in
    "mypackage" and in its subpackages. | 
! negators, just
    like file name filters. This notation doesn't look very Java-like, so it
    should be used with moderation.
    
    For convenience and for backward compatibility, the class name
    * refers to any class, irrespective of its package.
extends and implements
    specifications are typically used to restrict classes with wildcards. They
    are currently equivalent, specifying that only classes extending or
    implementing the given class qualify. Note that the given class itself is
    not included in this set. If required, it should be specified in a
    separate option.@ specifications can be used to restrict classes
    and class members to the ones that are annotated with the specified
    annotation types. An annotationtype is specified just like a
    classname.javadoc and javap). The specifications can
    also contain the following catch-all wildcards:
| <init> | matches any constructor. | 
| <fields> | matches any field. | 
| <methods> | matches any method. | 
| * | matches any field or method. | 
<init> wildcard has an argument list.
    Fields and methods may also be specified using regular expressions. Names can contain the following wildcards:
| ? | matches any single character in a method name. | 
| * | matches any part of a method name. | 
| % | matches any primitive type (" boolean", "int",
        etc, but not "void"). | 
| ? | matches any single character in a class name. | 
| * | matches any part of a class name not containing the package separator. | 
| ** | matches any part of a class name, possibly containing any number of package separators. | 
| *** | matches any type (primitive or non-primitive, array or non-array). | 
| ... | matches any number of arguments of any type. | 
?, *, and **
    wildcards will never match primitive types. Furthermore, only the
    *** wildcards will match array types of any dimension. For
    example, "** get*()" matches "java.lang.Object
    getObject()", but not "float getFloat()", nor
    "java.lang.Object[] getObjects()".! specifies that the corresponding access
    flag should be unset.
    
    Combining multiple flags is allowed (e.g. public static). It
    means that both access flags have to be set (e.g. public
    and static), except when they are conflicting, in
    which case at least one of them has to be set (e.g. at least
    public
    or protected).
    
    ProGuard supports the additional modifiers synthetic,
    bridge, and varargs, which may be
    set by compilers.