| To run ProGuard, just type: | |
| `bin/proguard `*options* ... | |
| Typically, you'll put most options in a configuration file (say, | |
| `myconfig.pro`), and just call: | |
| `bin/proguard @myconfig.pro` | |
| You can combine command line options and options from configuration | |
| files. For instance: | |
| `bin/proguard @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. | |
| ## Input/Output Options {: #iooptions} | |
| `@`{: #at} [*filename*](#filename) | |
| : Short for '[`-include`](#include) [*filename*](#filename)'. | |
| `-include`{: #include} [*filename*](#filename) | |
| : Recursively reads configuration options from the given file *filename*. | |
| `-basedirectory`{: #basedirectory} [*directoryname*](#filename) | |
| : Specifies the base directory for all subsequent relative file names in | |
| these configuration arguments or this configuration file. | |
| `-injars`{: #injars} [*class\_path*](#classpath) | |
| : Specifies the input jars (or apks, aabs, aars, wars, ears, jmods, zips, or | |
| directories) of the application to be processed. The class files in these | |
| jars will be processed and written to the output jars. By default, any | |
| non-class files will be copied without changes. Please be aware of any | |
| temporary files (e.g. created by IDEs), especially if you are reading your | |
| input files straight from directories. The entries in the class path can be | |
| filtered, as explained in the [filters](#filefilters) section. For better | |
| readability, class path entries can be specified using multiple `-injars` | |
| options. | |
| `-outjars`{: #outjars} [*class\_path*](#classpath) | |
| : Specifies the names of the output jars (or apks, aabs, aars, wars, ears, | |
| jmods, zips, or directories). The processed input of the preceding | |
| [`-injars`](usage.md#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](#filefilters) 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`](usage.md#outjars) options. Without any | |
| [`-outjars`](usage.md#outjars) options, no jars will be written. | |
| `-libraryjars`{: #libraryjars} [*class\_path*](#classpath) | |
| : Specifies the library jars (or apks, aabs, aars, wars, ears, jmods, zips, | |
| directories) of the application to be processed. The files in these jars | |
| will not be included in the output jars. 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, | |
| although their presence can improve the results of the optimization step. | |
| The entries in the class path can be filtered, as explained in the | |
| [filters](#filefilters) section. For better readability, class path entries | |
| can be specified using multiple `-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](examples.md#application) as well as [JME | |
| midlets](examples.md#midlet) or [Android | |
| apps](examples.md#androidapplication), just by specifying the appropriate | |
| run-time jar. | |
| `-skipnonpubliclibraryclasses`{: #skipnonpubliclibraryclasses} | |
| : Specifies to skip non-public classes while reading library jars, to speed | |
| up processing and reduce memory usage of ProGuard. By default, ProGuard | |
| reads non-public and public library classes alike. However, non-public | |
| classes are often not relevant, if they don't affect the actual program code | |
| in the input jars. Ignoring them then speeds up ProGuard, without affecting | |
| the output. Unfortunately, some libraries, including recent JSE run-time | |
| libraries, contain non-public library classes that are extended by public | |
| library classes. You then can't use this option. ProGuard will print out | |
| warnings if it can't find classes due to this option being set. | |
| `-dontskipnonpubliclibraryclasses`{: #dontskipnonpubliclibraryclasses} | |
| : Specifies not to ignore non-public library classes. As of version 4.5, | |
| this is the default setting. | |
| `-dontskipnonpubliclibraryclassmembers`{: #dontskipnonpubliclibraryclassmembers} | |
| : Specifies not to ignore package visible library class members (fields and | |
| methods). By default, ProGuard skips these class members while parsing | |
| library classes, as program classes will generally not refer to them. | |
| Sometimes however, program classes reside in the same packages as library | |
| classes, and they do refer to their package visible class members. In those | |
| cases, it can be useful to actually read the class members, in order to make | |
| sure the processed code remains consistent. | |
| `-keepdirectories`{: #keepdirectories} \[*[directory\_filter](#filefilters)*\] | |
| : Specifies the directories to be kept in the output jars (or apks, aabs, | |
| aars, wars, ears, jmods, zips, or directories). By default, directory | |
| entries are removed. This reduces the jar size, but it may break your | |
| program if the code tries to find them with constructs like | |
| "`com.example.MyClass.class.getResource("")`". You'll then want to keep the | |
| directory corresponding to the package, "`-keepdirectories com.example`". 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`{: #target} *version* | |
| : Specifies the version number to be set in the processed class files. The | |
| version number can be one of `1.0`,..., `1.9`, or the more recent short | |
| numbers `5`,..., `12`. By default, the version numbers of the class files | |
| are left unchanged. For example, you may want to [upgrade class files to | |
| Java 6](examples.md#upgrade). ProGuard changes their version numbers and | |
| preverifies them. You can also downgrade class files to older versions than | |
| Java 8. ProGuard changes their version numbers and backports Java 8 | |
| constructs. ProGuard generally doesn't backport changes in the Java runtime, | |
| except for the Java 8 stream API and the Java 8 date API, if you add the | |
| backported libraries `net.sourceforge.streamsupport` and `org.threeten` as | |
| input, respectively. | |
| `-forceprocessing`{: #forceprocessing} | |
| : Specifies to process the input, even if the output seems up to date. The | |
| up-to-dateness test is based on a comparison of the date stamps of the | |
| specified input, output, and configuration files or directories. | |
| ## Keep Options {: #keepoptions} | |
| `-keep`{: #keep} \[[,*modifier*](#keepoptionmodifiers),...\] [*class\_specification*](#classspecification) | |
| : Specifies classes and class members (fields and methods) to be preserved | |
| as entry points to your code. For example, in order to [keep an | |
| application](examples.md#application), you can specify the main class along | |
| with its main method. In order to [process a library](examples.md#library), | |
| you should specify all publicly accessible elements. | |
| `-keepclassmembers`{: #keepclassmembers} \[[,*modifier*](#keepoptionmodifiers),...\] [*class\_specification*](#classspecification) | |
| : 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](examples.md#serializable) of classes that implement the | |
| `Serializable` interface. | |
| `-keepclasseswithmembers`{: #keepclasseswithmembers} \[[,*modifier*](#keepoptionmodifiers),...\] [*class\_specification*](#classspecification) | |
| : 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](examples.md#applications) that have a main method, | |
| without having to list them explicitly. | |
| `-keepnames`{: #keepnames} [*class\_specification*](#classspecification) | |
| : Short for [`-keep`](#keep),[`allowshrinking`](#allowshrinking) | |
| [*class\_specification*](#classspecification) 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](examples.md#serializable) 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`{: #keepclassmembernames} [*class\_specification*](#classspecification) | |
| : Short for | |
| [`-keepclassmembers`](#keepclassmembers),[`allowshrinking`](#allowshrinking) | |
| [*class\_specification*](#classspecification) 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](examples.md#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`{: #keepclasseswithmembernames} [*class\_specification*](#classspecification) | |
| : Short for | |
| [`-keepclasseswithmembers`](#keepclasseswithmembers),[`allowshrinking`](#allowshrinking) | |
| [*class\_specification*](#classspecification) 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](examples.md#native) 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. | |
| `-if`{: #if} [*class\_specification*](#classspecification) | |
| : Specifies classes and class members that must be `present` to activate the | |
| subsequent keep option ([`-keep`](usage.md#keep), | |
| [`-keepclassmembers`](usage.md#keepclassmembers),...). The condition and | |
| the subsequent keep option can share wildcards and references to wildcards. | |
| For example, you can keep classes on the condition that classes with related | |
| names exist in your project, with frameworks like | |
| [Dagger](examples.md#dagger) and [Butterknife](examples.md#butterknife). | |
| `-printseeds`{: #printseeds} \[[*filename*](#filename)\] | |
| : Specifies to exhaustively list classes and class members matched by the | |
| various `-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](examples.md#applications) or all | |
| the [applets](examples.md#applets) that you are keeping. | |
| ## Shrinking Options {: #shrinkingoptions} | |
| `-dontshrink`{: #dontshrink} | |
| : Specifies not to shrink the input. By default, ProGuard shrinks the code: it | |
| removes all unused classes and class members. It only keeps the ones listed | |
| by the various [`-keep`](usage.md#keep) options, and the ones on which they | |
| depend, directly or indirectly. It also applies a shrinking step after each | |
| optimization step, since some optimizations may open up the possibility to | |
| remove more classes and class members. | |
| `-printusage`{: #printusage} \[[*filename*](#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](examples.md#deadcode). Only applicable when | |
| shrinking. | |
| `-whyareyoukeeping`{: #whyareyoukeeping} [*class\_specification*](#classspecification) | |
| : Specifies to print details on why the given classes and class members are | |
| being kept in the shrinking step. This can be useful if you are wondering | |
| why some given element is present in the output. In general, there can be | |
| many different reasons. This option prints the shortest chain of methods to | |
| a specified seed or entry point, for each specified class and class member. | |
| *In the current implementation, the shortest chain that is printed out may | |
| sometimes contain circular deductions -- these do not reflect the actual | |
| shrinking process.* If the [`-verbose`](#verbose) option if specified, the | |
| traces include full field and method signatures. Only applicable when | |
| shrinking. | |
| ## Optimization Options {: #optimizationoptions} | |
| `-dontoptimize`{: #dontoptimize} | |
| : Specifies not to optimize the input class files. By default, ProGuard | |
| optimizes all code. It inlines and merges classes and class members, and | |
| it optimizes all methods at a bytecode level. | |
| `-optimizations`{: #optimizations} [*optimization\_filter*](optimizations.md) | |
| : Specifies the optimizations to be enabled and disabled, at a more | |
| fine-grained level. Only applicable when optimizing. *This is an expert | |
| option.* | |
| `-optimizationpasses`{: #optimizationpasses} *n* | |
| : Specifies the number of optimization passes to be performed. By default, a | |
| single pass is performed. Multiple passes may result in further | |
| improvements. If no improvements are found after an optimization pass, the | |
| optimization is ended. Only applicable when optimizing. | |
| `-assumenosideeffects`{: #assumenosideeffects} [*class\_specification*](#classspecification) | |
| : Specifies methods that don't have any side effects, other than possibly | |
| returning a value. For example, the method `System.currentTimeMillis()` | |
| returns a value, but it doesn't have any side effects. In the optimization | |
| step, ProGuard can then remove calls to such methods, if it can determine | |
| that the return values aren't used. ProGuard will analyze your program code | |
| to find such methods automatically. It will not analyze library code, for | |
| which this option can therefore be useful. For example, you could specify | |
| the method `System.currentTimeMillis()`, so that any idle calls to it will | |
| be removed. With some care, you can also use the option to [remove logging | |
| code](examples.md#logging). 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!* | |
| `-assumenoexternalsideeffects`{: #assumenoexternalsideeffects} [*class\_specification*](#classspecification) | |
| : Specifies methods that don't have any side effects, except possibly on the | |
| instances on which they are called. This statement is weaker than | |
| [`-assumenosideeffects`](#assumenosideeffects), because it allows side | |
| effects on the parameters or the heap. For example, the | |
| `StringBuffer#append` methods have side effects, but no external side | |
| effects. This is useful when [removing logging code](examples.md#logging), | |
| to also remove any related string concatenation code. Only applicable when | |
| optimizing. Making assumptions can be dangerous; you can easily break the | |
| processed code. *Only use this option if you know what you're doing!* | |
| `-assumenoescapingparameters`{: #assumenoescapingparameters} [*class\_specification*](#classspecification) | |
| : Specifies methods that don't let their reference parameters escape to the | |
| heap. Such methods can use, modify, or return the parameters, but not store | |
| them in any fields, either directly or indirectly. For example, the method | |
| `System.arrayCopy` does not let its reference parameters escape, but method | |
| `System.setSecurityManager` does. Only applicable when optimizing. Making | |
| assumptions can be dangerous; you can easily break the processed code. *Only | |
| use this option if you know what you're doing!* | |
| `-assumenoexternalreturnvalues`{: #assumenoexternalreturnvalues} [*class\_specification*](#classspecification) | |
| : Specifies methods that don't return reference values that were already on | |
| the heap when they are called. For example, the `ProcessBuilder#start` | |
| returns a `Process` reference value, but it is a new instance that wasn't on | |
| the heap yet. Only applicable when optimizing. Making assumptions can be | |
| dangerous; you can easily break the processed code. *Only use this option if | |
| you know what you're doing!* | |
| `-assumevalues`{: #assumevalues} [*class\_specification*](#classspecification) | |
| : Specifies fixed values or ranges of values for primitive fields and | |
| methods. For example, you can [optimize your app for given Android SDK | |
| versions](examples.md#androidversions) by specifying the supported range in | |
| the version constant. ProGuard can then optimize away code paths for older | |
| versions. Making assumptions can be dangerous; you can easily break the | |
| processed code. *Only use this option if you know what you're doing!* | |
| `-allowaccessmodification`{: #allowaccessmodification} | |
| : Specifies that the access modifiers of classes and class members may be | |
| broadened during processing. This can improve the results of the | |
| optimization step. For instance, when inlining a public getter, it may be | |
| necessary to make the accessed field public too. Although Java's binary | |
| compatibility specifications formally do not require this (cfr. [The Java | |
| Language Specification, Third | |
| Edition](http://docs.oracle.com/javase/specs/jls/se12/html/index.html), | |
| [Section | |
| 13.4.6](http://docs.oracle.com/javase/specs/jls/se12/html/jls-13.html#jls-13.4.6)), | |
| some virtual machines would have problems with the processed code otherwise. | |
| Only applicable when optimizing (and when obfuscating with the | |
| [`-repackageclasses`](#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. | |
| `-mergeinterfacesaggressively`{: #mergeinterfacesaggressively} | |
| : Specifies that interfaces may be merged, even if their implementing | |
| classes don't implement all interface methods. This can reduce the size of | |
| the output by reducing the total number of classes. Note that Java's binary | |
| compatibility specifications allow such constructs (cfr. [The Java Language | |
| Specification, Third | |
| Edition](http://docs.oracle.com/javase/specs/jls/se12/html/index.html), | |
| [Section | |
| 13.5.3](http://docs.oracle.com/javase/specs/jls/se12/html/jls-13.html#jls-13.5.3)), | |
| even if they are not allowed in the Java language (cfr. [The Java Language | |
| Specification, Third | |
| Edition](http://docs.oracle.com/javase/specs/jls/se12/html/index.html), | |
| [Section | |
| 8.1.4](http://docs.oracle.com/javase/specs/jls/se12/html/jls-8.html#jls-8.1.4)). | |
| Only applicable when optimizing. | |
| *Counter-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: | |
| - Sun's JRE 1.3 may throw an `InternalError` when encountering | |
| more than 256 *Miranda* methods (interface methods | |
| without implementations) in a class. | |
| ## Obfuscation Options {: #obfuscationoptions} | |
| `-dontobfuscate`{: #dontobfuscate} | |
| : Specifies not to obfuscate the input class files. By default, ProGuard | |
| obfuscates the code: it assigns new short random names to classes and | |
| class members. It removes internal attributes that are only useful for | |
| debugging, such as source files names, variable names, and line numbers. | |
| `-printmapping`{: #printmapping} \[[*filename*](#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. For example, it is required for subsequent | |
| [incremental obfuscation](examples.md#incremental), or if you ever want to | |
| make sense again of [obfuscated stack traces](examples.md#stacktrace). Only | |
| applicable when obfuscating. | |
| `-applymapping`{: #applymapping} [*filename*](#filename) | |
| : Specifies to reuse the given name mapping that was printed out in a | |
| previous obfuscation run of ProGuard. Classes and class members that are | |
| listed in the mapping file receive the names specified along with them. | |
| Classes and class members that are not mentioned receive new names. The | |
| mapping may refer to input classes as well as library classes. This option | |
| can be useful for [incremental obfuscation](examples.md#incremental), i.e. | |
| processing add-ons or small patches to an existing piece of code. If the | |
| structure of the code changes fundamentally, ProGuard may print out warnings | |
| that applying a mapping is causing conflicts. You may be able to reduce this | |
| risk by specifying the option | |
| [`-useuniqueclassmembernames`](#useuniqueclassmembernames) in both | |
| obfuscation runs. Only a single mapping file is allowed. Only applicable | |
| when obfuscating. | |
| `-obfuscationdictionary`{: #obfuscationdictionary} [*filename*](#filename) | |
| : Specifies a text file from which all valid words are used as obfuscated | |
| field and method names. By default, short names like 'a', 'b', etc. are used | |
| as obfuscated names. With an obfuscation dictionary, you can specify a list | |
| of reserved key words, or identifiers with foreign characters, for instance. | |
| White space, punctuation characters, duplicate words, and comments after a | |
| `#` 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`{: #classobfuscationdictionary} [*filename*](#filename) | |
| : Specifies a text file from which all valid words are used as obfuscated | |
| class names. The obfuscation dictionary is similar to the one of the option | |
| [`-obfuscationdictionary`](#obfuscationdictionary). Only applicable when | |
| obfuscating. | |
| `-packageobfuscationdictionary`{: #packageobfuscationdictionary} [*filename*](#filename) | |
| : Specifies a text file from which all valid words are used as obfuscated | |
| package names. The obfuscation dictionary is similar to the one of the | |
| option [`-obfuscationdictionary`](#obfuscationdictionary). Only applicable | |
| when obfuscating. | |
| `-overloadaggressively`{: #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, as required by Java bytecode (not just their | |
| arguments, as required by the Java language). This option can make the | |
| processed code even smaller (and less comprehensible). Only applicable when | |
| obfuscating. | |
| *Counter-indication:* the resulting class files fall within the Java | |
| bytecode specification (cfr. [The Java Virtual Machine | |
| Specification](http://docs.oracle.com/javase/specs/jvms/se12/html/index.html), | |
| first paragraphs of [Section | |
| 4.5](http://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.5) | |
| and [Section | |
| 4.6](http://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.6)), | |
| even though this kind of overloading is not allowed in the Java language | |
| (cfr. [The Java Language Specification, Third | |
| Edition](http://docs.oracle.com/javase/specs/jls/se12/html/index.html), | |
| [Section | |
| 8.3](http://docs.oracle.com/javase/specs/jls/se12/html/jls-8.html#jls-8.3) | |
| and [Section | |
| 8.4.5](http://docs.oracle.com/javase/specs/jls/se12/html/jls-8.html#jls-8.4.5)). | |
| Still, some tools have problems with it. Notably: | |
| - Sun's JDK 1.2.2 `javac` compiler produces an exception when | |
| compiling with such a library (cfr. [Bug | |
| \#4216736](http://bugs.sun.com/view_bug.do?bug_id=4216736)). You | |
| probably shouldn't use this option for processing libraries. | |
| - Sun's JRE 1.4 and later fail to serialize objects with | |
| overloaded primitive fields. | |
| - Sun's JRE 1.5 `pack200` tool reportedly has problems with | |
| overloaded class members. | |
| - The class `java.lang.reflect.Proxy` can't handle | |
| overloaded methods. | |
| - Google's Dalvik VM can't handle overloaded static fields. | |
| `-useuniqueclassmembernames`{: #useuniqueclassmembernames} | |
| : Specifies to assign the same obfuscated names to class members that have | |
| the same names, and different obfuscated names to class members that have | |
| different names (for each given class member signature). Without the option, | |
| more class members can be mapped to the same short names like 'a', 'b', etc. | |
| The option therefore increases the size of the resulting code slightly, but | |
| it ensures that the saved obfuscation name mapping can always be respected | |
| in subsequent incremental obfuscation steps. | |
| For 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`{: #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 can use this | |
| option to switch off this behavior. Obfuscated jars will become slightly | |
| larger as a result. Only applicable when obfuscating. | |
| `-keeppackagenames`{: #keeppackagenames} \[*[package\_filter](#filters)*\] | |
| : Specifies not to obfuscate the given package names. The optional filter is | |
| a comma-separated list of package names. Package names can contain **?**, | |
| **\***, and **\*\*** wildcards, and they can be preceded by the **!** | |
| negator. Only applicable when obfuscating. | |
| `-flattenpackagehierarchy`{: #flattenpackagehierarchy} \[*package\_name*\] | |
| : Specifies to repackage all packages that are renamed, by moving them into | |
| the single given parent package. Without argument or with an empty string | |
| (''), the packages are moved into the root package. This option is one | |
| example of further [obfuscating package names](examples.md#repackaging). It | |
| can make the processed code smaller and less comprehensible. Only applicable | |
| when obfuscating. | |
| `-repackageclasses`{: #repackageclasses} \[*package\_name*\] | |
| : Specifies to repackage all class files that are renamed, by moving them | |
| into the single given package. Without argument or with an empty string | |
| (''), the package is removed completely. This option overrides the | |
| [`-flattenpackagehierarchy`](#flattenpackagehierarchy) option. It is another | |
| example of further [obfuscating package names](examples.md#repackaging). | |
| 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. | |
| *Note:* On Android, you should not use the empty string when classes like | |
| activities, views, etc. may be renamed. The Android run-time automatically | |
| prefixes package-less names in XML files with the application package name | |
| or with `android.view`. This is unavoidable but it breaks the application | |
| in this case. | |
| `-keepattributes`{: #keepattributes} \[*[attribute\_filter](attributes.html)*\] | |
| : Specifies any optional attributes to be preserved. The attributes can be | |
| specified with one or more [`-keepattributes`](usage.md#keepattributes) | |
| directives. The optional filter is a comma-separated list of [attribute | |
| names](attributes.html) 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](examples.md#library). You should also keep the | |
| `SourceFile` and `LineNumberTable` attributes for [producing useful | |
| obfuscated stack traces](examples.md#stacktrace). Finally, you may want to | |
| [keep annotations](examples.md#annotations) if your code depends on them. | |
| Only applicable when obfuscating. | |
| `-keepparameternames`{: #keepparameternames} | |
| : Specifies to keep the parameter names and types of methods that are kept. | |
| This option actually keeps trimmed versions of the debugging attributes | |
| `LocalVariableTable` and `LocalVariableTypeTable`. It can be useful when | |
| [processing a library](examples.md#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`{: #renamesourcefileattribute} \[*string*\] | |
| : Specifies a constant string to be put in the `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`](usage.md#keepattributes) directive. For example, you | |
| may want to have your processed libraries and applications produce [useful | |
| obfuscated stack traces](examples.md#stacktrace). Only applicable when | |
| obfuscating. | |
| `-adaptclassstrings`{: #adaptclassstrings} \[*[class\_filter](#filters)*\] | |
| : Specifies that string constants that correspond to class names should be | |
| obfuscated as well. Without a filter, all string constants that correspond | |
| to class names are adapted. With a filter, only string constants in classes | |
| that match the filter are adapted. For example, if your code contains a | |
| large number of hard-coded strings that refer to classes, and you prefer not | |
| to keep their names, you may want to use this option. Primarily applicable | |
| when obfuscating, although corresponding classes are automatically kept in | |
| the shrinking step too. | |
| `-adaptresourcefilenames`{: #adaptresourcefilenames} \[*[file\_filter](#filefilters)*\] | |
| : Specifies the resource files to be renamed, based on the obfuscated names | |
| of the corresponding class files (if any). Without a filter, all resource | |
| files that correspond to class files are renamed. With a filter, only | |
| matching files are renamed. For example, see [processing resource | |
| files](examples.md#resourcefiles). Only applicable when obfuscating. | |
| `-adaptresourcefilecontents`{: #adaptresourcefilecontents} \[*[file\_filter](#filefilters)*\] | |
| : Specifies the resource files and native libraries whose contents are to be | |
| updated. Any class names mentioned in the resource files are renamed, based | |
| on the obfuscated names of the corresponding classes (if any). Any function | |
| names in the native libraries are renamed, based on the obfuscated names of | |
| the corresponding native methods (if any). Without a filter, the contents of | |
| all resource files updated. With a filter, only matching files are updated. | |
| The resource files are parsed and written using UTF-8 encoding. For an | |
| example, see [processing resource files](examples.md#resourcefiles). Only | |
| applicable when obfuscating. *Caveat:* You probably only want to apply this | |
| option to text files and native libraries, since parsing and adapting | |
| general binary files as text files can cause unexpected problems. Therefore, | |
| make sure that you specify a sufficiently narrow filter. | |
| ## Preverification Options {: #preverificationoptions} | |
| `-dontpreverify`{: #dontpreverify} | |
| : Specifies not to preverify the processed class files. By default, class | |
| files are preverified if they are targeted at Java Micro Edition or at Java | |
| 6 or higher. For Java Micro Edition, preverification is required, so you | |
| will need to run an external preverifier on the processed code if you | |
| specify this option. For Java 6, preverification is optional, but as of Java | |
| 7, it is required. Only when eventually targeting Android, it is not | |
| necessary, so you can then switch it off to reduce the processing time a | |
| bit. | |
| `-microedition`{: #microedition} | |
| : Specifies that the processed class files are targeted at Java Micro | |
| Edition. The preverifier will then add the appropriate StackMap attributes, | |
| which are different from the default StackMapTable attributes for Java | |
| Standard Edition. For example, you will need this option if you are | |
| [processing midlets](examples.md#midlets). | |
| `-android`{: #android} | |
| : Specifies that the processed class files are targeted at the Android | |
| platform. ProGuard then makes sure some features are compatible with | |
| Android. For example, you should specify this option if you are [processing | |
| an Android application](examples.md#androidapplication). | |
| ## General Options {: #generaloptions} | |
| `-verbose`{: #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. | |
| `-dontnote`{: #dontnote} \[*[class\_filter](#filters)*\] | |
| : Specifies not to print notes about potential mistakes or omissions in the | |
| configuration, such as typos in class names or missing options that might be | |
| useful. The optional filter is a regular expression; ProGuard doesn't print | |
| notes about classes with matching names. | |
| `-dontwarn`{: #dontwarn} \[*[class\_filter](#filters)*\] | |
| : Specifies not to warn about unresolved references and other important | |
| problems at all. The optional filter is a regular expression; ProGuard | |
| doesn't print warnings about classes with matching names. Ignoring warnings | |
| can be dangerous. For instance, if the unresolved classes or class members | |
| are indeed required for processing, the processed code will not function | |
| properly. *Only use this option if you know what you're doing!* | |
| `-ignorewarnings`{: #ignorewarnings} | |
| : Specifies to print any warnings about unresolved references and other | |
| important problems, but to continue processing in any case. Ignoring | |
| warnings can be dangerous. For instance, if the unresolved classes or class | |
| members are indeed required for processing, the processed code will not | |
| function properly. *Only use this option if you know what you're doing!* | |
| `-printconfiguration`{: #printconfiguration} \[[*filename*](#filename)\] | |
| : Specifies to write out the entire configuration that has been parsed, with | |
| included files and replaced variables. The structure is printed to the | |
| standard output or to the given file. This can sometimes be useful to | |
| debug configurations, or to convert XML configurations into a more | |
| readable format. | |
| `-dump`{: #dump} \[[*filename*](#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](examples.md#structure), without processing it at all. | |
| `-addconfigurationdebugging`{: #addconfigurationdebugging} | |
| : Specifies to instrument the processed code with debugging statements that | |
| print out suggestions for missing ProGuard configuration. This can be very | |
| useful to get practical hints _at run-time_, if your processed code crashes | |
| because it still lacks some configuration for reflection. For example, the | |
| code may be [serializing classes with the GSON library](examples.md#gson) | |
| and you may need some configuration for it. You can generally just | |
| copy/paste the suggestions from the console into your configuration file. | |
| *Counter-indication:* do not use this option in release versions, as it adds | |
| obfuscation information to the processed code. | |
| ## Class Paths {: #classpath} | |
| ProGuard accepts a generalization of class paths to specify input files | |
| and output files. A class path consists of entries, separated by the | |
| traditional path separator (e.g. '**:**' on Unix, or '**;**' on Windows | |
| platforms). The order of the entries determines their priorities, in | |
| case of duplicates. | |
| Each input entry can be: | |
| - A class file or resource file, | |
| - An apk file, containing any of the above, | |
| - A jar file, containing any of the above, | |
| - An aar file, containing any of the above, | |
| - A war file, containing any of the above, | |
| - An ear file, containing any of the above, | |
| - A jmod file, containing any of the above, | |
| - A zip file, containing any of the above, | |
| - A directory (structure), containing any of the above. | |
| 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: | |
| - An apk file, in which all class files and resource files will | |
| be collected. | |
| - A jar file, in which any and all of the above will be collected, | |
| - An aar file, in which any and all of the above will be collected, | |
| - A war file, in which any and all of the above will be collected, | |
| - An ear file, in which any and all of the above will be collected, | |
| - A jmod file, in which any and all of the above will be collected, | |
| - A zip file, in which any and all of the above will be collected, | |
| - A directory, in which any and all of the above will be collected. | |
| When writing output entries, ProGuard generally packages 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](examples.md#restructuring). | |
| Files and directories can be specified as discussed in the section on | |
| [file names](#filename) 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 8 types of [file | |
| filters](#filefilters) between parentheses, separated by semi-colons: | |
| - A filter for all jmod names that are encountered, | |
| - A filter for all aar names that are encountered, | |
| - A filter for all apk names that are encountered, | |
| - A filter for all zip names that are encountered, | |
| - A filter for all ear names that are encountered, | |
| - A filter for all war names that are encountered, | |
| - A filter for all jar names that are encountered, | |
| - A filter for all class file names and resource file names that | |
| are encountered. | |
| If fewer than 8 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([[[[[[[jmodfilter;]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](examples.md#filtering). | |
| ## File Names {: #filename} | |
| ProGuard accepts absolute paths and relative paths for the various file | |
| names and directory names. A relative path is interpreted as follows: | |
| - relative to the base directory, if set, or otherwise | |
| - relative to the configuration file in which it is specified, if any, | |
| or otherwise | |
| - relative to the working directory. | |
| 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"'`. | |
| ## File Filters {: #filefilters} | |
| Like general [filters](#filters), a file filter is a comma-separated | |
| list of 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 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. | |
| For example, "`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](examples.md#filtering). | |
| ## Filters {: #filters} | |
| ProGuard offers options with filters for many different aspects of the | |
| configuration: names of files, directories, classes, packages, | |
| attributes, optimizations, etc. | |
| 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. | |
| For example, "`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`. | |
| ## Overview of `Keep` Options {: #keepoverview} | |
| The various [`-keep`](usage.md#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`](#keep) | [`-keepnames`](#keepnames) | |
| | Class members only | [`-keepclassmembers`](#keepclassmembers) | [`-keepclassmembernames`](#keepclassmembernames) | |
| | Classes and class members, if class members present | [`-keepclasseswithmembers`](#keepclasseswithmembers) | [`-keepclasseswithmembernames`](#keepclasseswithmembernames) | |
| Each of these [`-keep`](usage.md#keep) options is of course followed by a | |
| [specification](#classspecification) 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. | |
| !!! warning "" | |
| - If you specify a class, without class members, ProGuard only | |
| preserves the class and its parameterless constructor as | |
| entry points. It may still remove, optimize, or obfuscate its other | |
| class members. | |
| - If you specify a method, ProGuard only preserves the method as an | |
| entry point. Its code may still be optimized and adapted. | |
| ## Keep Option Modifiers {: #keepoptionmodifiers} | |
| `includedescriptorclasses` | |
| : Specifies that any classes in the type descriptors of the methods and | |
| fields that the [-keep](#keep) option keeps should be kept as well. This is | |
| typically useful when [keeping native method names](examples.md#native), to | |
| make sure that the parameter types of native methods aren't renamed either. | |
| Their signatures then remain completely unchanged and compatible with the | |
| native libraries. | |
| `includecode` | |
| : Specifies that code attributes of the methods that the [-keep](#keep) | |
| option keeps should be kept as well, i.e. may not be optimized or obfuscated. | |
| This is typically useful for already optimized or obfuscated classes, | |
| to make sure that their code is not modified during optimization. | |
| `allowshrinking` | |
| : Specifies that the entry points specified in the [-keep](#keep) option may | |
| be shrunk, even if they have to be preserved otherwise. That is, the entry | |
| points may be removed in the shrinking step, but if they are necessary after | |
| all, they may not be optimized or obfuscated. | |
| `allowoptimization` | |
| : Specifies that the entry points specified in the [-keep](#keep) option may | |
| be optimized, even if they have to be preserved otherwise. That is, the | |
| entry points may be altered in the optimization step, but they may not be | |
| removed or obfuscated. This modifier is only useful for achieving unusual | |
| requirements. | |
| `allowobfuscation` | |
| : Specifies that the entry points specified in the [-keep](#keep) option may | |
| be obfuscated, even if they have to be preserved otherwise. That is, the | |
| entry points may be renamed in the obfuscation step, but they may not be | |
| removed or optimized. This modifier is only useful for achieving unusual | |
| requirements. | |
| ## Class Specifications {: #classspecification} | |
| A class specification is a template of classes and class members (fields | |
| and methods). It is used in the various [`-keep`](usage.md#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](examples.md), 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 [= values]); | |
| [@annotationtype] | |
| [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] | |
| <methods> | <init>(argumenttype,...) | classname(argumenttype,...) | (returntype methodname(argumenttype,...) [return values]); | |
| }] | |
| 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. | |
| - The `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. | |
| - Every *classname* must be fully qualified, e.g. `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, "`com.example.Test?`" matches "`com.example.Test1`" and "`com.example.Test2`", but not "`com.example.Test12`". | |
| | `*` | matches any part of a class name not containing the package separator. For example, "`com.example.*Test*`" matches "`com.example.Test`" and "`com.example.YourTestApplication`", but not "`com.example.mysubpackage.MyTest`". Or, more generally, "`com.example.*`" matches all classes in "`com.example`", but not in its subpackages. | |
| | `**` | matches any part of a class name, possibly containing any number of package separators. For example, "`**.Test`" matches all `Test` classes in all packages except the root package. Or, "`com.example.**`" matches all classes in "`com.example`" and in its subpackages. | |
| | `<n>` | matches the _n_'th matched wildcard in the same option. For example, "`com.example.*Foo<1>`" matches "`com.example.BarFooBar`". | |
| For additional flexibility, class names can actually be | |
| comma-separated lists of class names, with optional `!` 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. | |
| - The `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 (directly or indirectly) qualify. The given class itself is not | |
| included in this set. If required, it should be specified in a separate | |
| option. | |
| - The `@` 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*. | |
| - Fields and methods are specified much like in Java, except that | |
| method argument lists don't contain argument names (just like in | |
| other tools like `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. | |
| Note that the above wildcards don't have return types. Only the | |
| `<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. | |
| | `<n>` | matches the _n_'th matched wildcard in the same option. | |
| Types in descriptors can contain the following wildcards: | |
| | | | |
| |-------|----------------------------------------------------------------------------------------- | |
| | `%` | 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. | |
| | `<n>` | matches the _n_'th matched wildcard in the same option. | |
| Note that the `?`, `*`, 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()`". | |
| - Constructors can also be specified using their short class names | |
| (without package) or using their full class names. As in the Java | |
| language, the constructor specification has an argument list, but no | |
| return type. | |
| - The class access modifiers and class member access modifiers are | |
| typically used to restrict wildcarded classes and class members. | |
| They specify that the corresponding access flags have to be set for | |
| the member to match. A preceding `!` 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. | |
| - With the option [`-assumevalues`](#assumevalues), fields and methods | |
| with primitive return types can have *values* or *ranges of values*. | |
| The assignment keyword is `=` or `return`, interchangeably. For | |
| example, "`boolean flag = true;`" or "`int method() return 5;`". | |
| Ranges of values are separated by `..`, for example, | |
| "`int f = 100..200;`". A range includes its begin value and | |
| end value. |