java -jar proguard.jar
options ...
java -jar proguard.jar @myconfig.pro
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 -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.
@
filename-include
filename'.-include
filename-libraryjars
class_path-libraryjars
options.
Please note that the boot path and 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 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
class_path-resourcejars
option. Please be aware of any
temporary files (e.g. created by IDEs), especially if you are reading your
input files straight from directories. The files in the class path can be
filtered based on their names, as explained in the class path section. It
is allowed to specify multiple -injars
options.-resourcejars
class_path-resourcejars
options. Without this option, the resource files from the program jars (or
directories) will be copied.-outjars
class_path-outjars
options. The output files must never overwrite any input files. Without
this option, no jars or class files will be written.-keep
class_specification-keepclassmembers
class_specificationSerializable
interface.-keepclasseswithmembers
class_specification-keepnames
class_specificationSerializable
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_specificationclass$
methods when processing a library, so ProGuard can
detect it again when processing an application that uses the processed
library.-keepclasseswithmembernames
class_specification-keepattributes
[attribute_name,...]-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
,
SourceDir
, 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]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.-printseeds
[filename]-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]-printmapping
[filename]-applymapping
filename-verbose
-dump
[filename]-ignorewarnings
-dontwarn
-dontnote
-dontshrink
-keep
commands, and the ones they
depend on, recursively.-dontobfuscate
-keep
commands.
Internal attributes that are useful for debugging, such as source files
names, variable names, and line numbers are removed.-dontusemixedcaseclassnames
-overloadaggressively
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]Note that this kind of repackaging could 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. Although this is formally allowed by Java's binary compatibility specifications (cfr. The Java Language Specification, Second Edition, Section 13.4.6), some virtual machines have problems with it. ProGuard works around it by making package visible classes and class members public, if this option is being used. These changes don't affect the functioning of applications. It might be confusing and therefore less desirable when processing libraries.
Counter-indications: 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.
-dontskipnonpubliclibraryclasses
-keep
Options-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 of these -keep
options is of course followed by a
specification of the classes and class
members 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 preserved from shrinking and from obfuscation.
In addition, ProGuard provides the possibility to filter the files in the class path, based on the file names. Each jar or diectory can be followed by a filter between parentheses. A filter consists of one or more comma-separated file names that can contain wildcards. Only files with matching file names are read (in the case of input jars), or written (in the case of output jars). The following wildcards are supported:
? |
matches any single character. |
* |
matches any string not containing the directory separator. |
** |
matches any string, possibly containing any number of directory separators. |
rt.jar(java/**.class,javax/**.class)
" matches all
class files in the java
and javax
directories inside
the rt
jar.
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, "input.jar(!images/**,**)
" matches all files, except
those in the images
directory, inside the input
jar.
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"'
.
-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.
class
keyword refers to any interface or class.
The interface
keyword restricts matches to interface
classes. Preceding the interface
keyword by a
!
restricts matches to classes that are not
interfaces.
java.lang.String
. Class names may be specified as regular
expressions containing the following wildcards:
? |
matches any single character, but not the package separator. For example,
"mypackage.Test? " matches "mypackage.Test1 " and
"mypackage.Test2 ", but not
"mypackage.Test12 ". |
* |
matches any string 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 string, possibly containing any number of package separators.
For example, "**.Test "
matches all Test classes in all packages except the root
package. Or, "mypackage.** " matches all classes in
"mypackage " and in its subpackages. |
*
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.
<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. |
* |
matches any string. |
? |
matches any single character. |
* |
matches any string not containing the package separator. |
** |
matches any string, possibly containing any number of package separators. |
** 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
).