| <!doctype html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> | |
| <meta http-equiv="content-style-type" content="text/css"> | |
| <link rel="stylesheet" type="text/css" href="style.css"> | |
| <title>ProGuard Examples</title> | |
| </head> | |
| <body> | |
| <script type="text/javascript" language="JavaScript"> | |
| <!-- | |
| if (window.self==window.top) | |
| document.write('<a class="largebutton" target="_top" href="../index.html#manual/examples.html">ProGuard index</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a>') | |
| //--> | |
| </script> | |
| <noscript> | |
| <a class="largebutton" target="_top" href="../index.html#manual/examples.html">ProGuard index</a> | |
| <a class="largebutton" target="_top" href="http://www.guardsquare.com/dexguard">DexGuard</a> | |
| <a class="largebutton" target="_top" href="http://www.guardsquare.com/">GuardSquare</a> | |
| <a class="largebutton" target="other" href="http://sourceforge.net/projects/proguard/">Sourceforge</a> | |
| </noscript> | |
| <h2>Examples</h2> | |
| Some typical useful configurations: | |
| <ol> | |
| <li><a href="#application">A typical application</a></li> | |
| <li><a href="#applet">A typical applet</a></li> | |
| <li><a href="#midlet">A typical midlet</a></li> | |
| <li><a href="#jcapplet">A typical Java Card applet</a></li> | |
| <li><a href="#xlet">A typical xlet</a></li> | |
| <li><a href="#androidactivity">A simple Android activity</a></li> | |
| <li><a href="#androidapplication">A complete Android application</a></li> | |
| <li><a href="#library">A typical library</a></li> | |
| <li><a href="#applications">All possible applications in the input jars</a></li> | |
| <li><a href="#applets">All possible applets in the input jars</a></li> | |
| <li><a href="#midlets">All possible midlets in the input jars</a></li> | |
| <li><a href="#jcapplets">All possible Java Card applets in the input jars</a></li> | |
| <li><a href="#xlets">All possible xlets in the input jars</a></li> | |
| <li><a href="#servlets">All possible servlets in the input jars</a></li> | |
| <li><a href="#scala">Scala applications with the Scala runtime</a></li> | |
| <li><a href="#native">Processing native methods</a></li> | |
| <li><a href="#callback">Processing callback methods</a></li> | |
| <li><a href="#enumerations">Processing enumeration classes</a></li> | |
| <li><a href="#serializable">Processing serializable classes</a></li> | |
| <li><a href="#beans">Processing bean classes</a></li> | |
| <li><a href="#annotations">Processing annotations</a></li> | |
| <li><a href="#database">Processing database drivers</a></li> | |
| <li><a href="#componentui">Processing ComponentUI classes</a></li> | |
| <li><a href="#rmi">Processing RMI code</a></li> | |
| <li><a href="#injection">Processing dependency injection</a></li> | |
| <li><a href="#dagger">Processing Dagger code</a></li> | |
| <li><a href="#butterknife">Processing Butterknife code</a></li> | |
| <li><a href="#resourcefiles">Processing resource files</a></li> | |
| <li><a href="#manifestfiles">Processing manifest files</a></li> | |
| <li><a href="#stacktrace">Producing useful obfuscated stack traces</a></li> | |
| <li><a href="#repackaging">Obfuscating package names</a></li> | |
| <li><a href="#logging">Removing logging code</a></li> | |
| <li><a href="#restructuring">Restructuring the output archives</a></li> | |
| <li><a href="#filtering">Filtering the input and the output</a></li> | |
| <li><a href="#multiple">Processing multiple applications at once</a></li> | |
| <li><a href="#incremental">Incremental obfuscation</a></li> | |
| <li><a href="#microedition">Preverifying class files for Java Micro Edition</a></li> | |
| <li><a href="#upgrade">Upgrading class files to Java 6</a></li> | |
| <li><a href="#deadcode">Finding dead code</a></li> | |
| <li><a href="#structure">Printing out the internal structure of class files</a></li> | |
| <li><a href="#annotated">Using annotations to configure ProGuard</a></li> | |
| </ol> | |
| You can find some sample configuration files in the <code>examples</code> | |
| directory of the ProGuard distribution. | |
| <h3><a name="application">A typical application</a></h3> | |
| To shrink, optimize, and obfuscate a simple Java application, you typically | |
| create a configuration file like <code>myconfig.pro</code>, which can be used | |
| with | |
| <pre> | |
| bin/proguard @myconfig.pro | |
| </pre> | |
| <p> | |
| The configuration file specifies the input, the output, and the entry points | |
| of the application: | |
| <pre> | |
| -injars myapplication.jar | |
| -outjars myapplication_out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -printmapping myapplication.map | |
| -keep public class mypackage.MyMain { | |
| public static void main(java.lang.String[]); | |
| } | |
| </pre> | |
| <p> | |
| Note the use of the <code><java.home></code> system property. ProGuard | |
| automatically replaces it when parsing the file. | |
| <p> | |
| The <a href="usage.html#keep"><code>-keep</code></a> option specifies the | |
| entry point of the application that has to be preserved. | |
| The access modifiers <code>public</code> and <code>static</code> are not | |
| really required in this case, since we know a priori that the specified class | |
| and method have the proper access flags. It just looks more familiar this way. | |
| <p> | |
| Note that all type names are fully specified: | |
| <code>mypackage.MyMain</code> and <code>java.lang.String[]</code>. | |
| <p> | |
| We're writing out an obfuscation mapping file with <a | |
| href="usage.html#printmapping"><code>-printmapping</code></a>, for | |
| de-obfuscating any stack traces later on, or for incremental obfuscation of | |
| extensions. | |
| <p> | |
| We can further improve the results with a few additional options: | |
| <pre> | |
| -optimizationpasses 3 | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| </pre> | |
| These options are not required; they just shave off some extra bytes from the | |
| output jar, by performing up to 3 optimization passes, and by aggressively | |
| obfuscating class members and <a href="#repackaging">package names</a>. | |
| <p> | |
| In general, you might need a few additional options for processing <a | |
| href="#native">native methods</a>, <a href="#callback">callback methods</a>, | |
| <a href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="applet">A typical applet</a></h3> | |
| These options shrink, optimize, and obfuscate the applet | |
| <code>mypackage.MyApplet</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -keep public class mypackage.MyApplet | |
| </pre> | |
| <p> | |
| The typical applet methods will be preserved automatically, since | |
| <code>mypackage.MyApplet</code> is an extension of the <code>Applet</code> | |
| class in the library <code>rt.jar</code>. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, <a | |
| href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="midlet">A typical midlet</a></h3> | |
| These options shrink, optimize, obfuscate, and preverify the midlet | |
| <code>mypackage.MyMIDlet</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -microedition | |
| -keep public class mypackage.MyMIDlet | |
| </pre> | |
| <p> | |
| Note how we're now targeting the Java Micro Edition run-time environment of | |
| <code>midpapi20.jar</code> and <code>cldcapi11.jar</code>, instead of the Java | |
| Standard Edition run-time environment <code>rt.jar</code>. You can target | |
| other JME environments by picking the appropriate jars. | |
| <p> | |
| The typical midlet methods will be preserved automatically, since | |
| <code>mypackage.MyMIDlet</code> is an extension of the <code>MIDlet</code> | |
| class in the library <code>midpapi20.jar</code>. | |
| <p> | |
| The <a href="usage.html#microedition"><code>-microedition</code></a> option | |
| makes sure the class files are preverified for Java Micro Edition, producing | |
| compact <code>StackMap</code> attributes. It is no longer necessary to run an | |
| external preverifier. | |
| <p> | |
| Be careful if you do use the external <code>preverify</code> tool on a platform | |
| with a case-insensitive filing system, such as Windows. Because this tool | |
| unpacks your processed jars, you should then use ProGuard's <a | |
| href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a> | |
| option. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a> and <a href="#resourcefiles">resource files</a>. | |
| <p> | |
| Note that you will still have to adapt the midlet jar size in the | |
| corresponding jad file; ProGuard doesn't do that for you. | |
| <h3><a name="jcapplet">A typical Java Card applet</a></h3> | |
| These options shrink, optimize, and obfuscate the Java Card applet | |
| <code>mypackage.MyApplet</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/javacard2.2.2/lib/api.jar | |
| -dontwarn java.lang.Class | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -keep public class mypackage.MyApplet | |
| </pre> | |
| <p> | |
| The configuration is very similar to the configuration for midlets, except that | |
| it now targets the Java Card run-time environment. This environment doesn't | |
| have java.lang.Class, so we're telling ProGuard not to worry about it. | |
| <h3><a name="xlet">A typical xlet</a></h3> | |
| These options shrink, optimize, and obfuscate the xlet | |
| <code>mypackage.MyXlet</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/jtv1.1/javatv.jar | |
| -libraryjars /usr/local/java/cdc1.1/lib/cdc.jar | |
| -libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -keep public class mypackage.MyXlet | |
| </pre> | |
| <p> | |
| The configuration is very similar to the configuration for midlets, except that | |
| it now targets the CDC run-time environment with the Java TV API. | |
| <h3><a name="androidactivity">A simple Android activity</a></h3> | |
| These options shrink, optimize, and obfuscate the single Android | |
| activity <code>mypackage.MyActivity</code>: | |
| <pre> | |
| -injars bin/classes | |
| -outjars bin/classes-processed.jar | |
| -libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar | |
| -dontpreverify | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -optimizations !code/simplification/arithmetic | |
| -keep public class mypackage.MyActivity | |
| </pre> | |
| <p> | |
| We're targeting the Android run-time and keeping the activity as an entry | |
| point. | |
| <p> | |
| Preverification is irrelevant for the dex compiler and the Dalvik VM, so we | |
| can switch it off with the | |
| <a href="usage.html#dontpreverify"><code>-dontpreverify</code></a> option. | |
| <p> | |
| The <a href="usage.html#optimizations"><code>-optimizations</code></a> option | |
| disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle. | |
| Note that the Dalvik VM also can't | |
| handle <a href="usage.html#overloadaggressively">aggressive overloading</a> | |
| (of static fields). | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, | |
| <a href="#enumerations">enumerations</a>, | |
| <a href="#annotations">annotations</a>, and | |
| <a href="#resourcefiles">resource files</a>. | |
| <h3><a name="androidapplication">A complete Android application</a></h3> | |
| <img class="float" src="attention.gif" width="64" height="64" alt="attention" | |
| /> The standard build processes of the Android SDK (with Ant, Gradle, Android | |
| Studio, and Eclipse) already integrate ProGuard with all the proper settings. | |
| You only need to enable ProGuard by uncommenting the line | |
| "<code>proguard.config=.....</code>" in the | |
| file <code>project.properties</code> (created or updated by Android SDK | |
| revision 17 or higher) or by adapting your <code>build.gradle</code> file. You | |
| then <em>don't</em> need any of the configuration below. | |
| <p> | |
| Notes: | |
| <ul> | |
| <li>In case of problems, you may want to check if the configuration files that | |
| are listed on this line (<code>proguard-project.txt</code>,...) contain | |
| the necessary settings for your application.</li> | |
| <li>Android SDK revision 20 and higher have a different configuration file for | |
| enabling optimization: | |
| <code>${sdk.dir}/tools/proguard/proguard-android-optimize.txt</code> | |
| instead of the default | |
| <code>${sdk.dir}/tools/proguard/proguard-android.txt</code>.</li> | |
| <li>The build processes are already setting the necessary program jars, | |
| library jars, and output jars for you — don't specify them again.</li> | |
| <li>If you get warnings about missing referenced classes: it's all too common | |
| that libraries refer to missing classes. | |
| See <a href="troubleshooting.html#unresolvedclass">"Warning: can't find | |
| referenced class"</a> in the Troubleshooting section.</li> | |
| </ul> | |
| <p> | |
| For more information, you can consult the official <a target="other" | |
| href="http://developer.android.com/guide/developing/tools/proguard.html">Developer | |
| Guide</a> in the Android SDK. | |
| <p> | |
| If you're constructing a build process <em>from scratch</em>: these options | |
| shrink, optimize, and obfuscate all public activities, services, broadcast | |
| receivers, and content providers from the compiled classes and external | |
| libraries: | |
| <pre> | |
| -injars bin/classes | |
| -injars libs | |
| -outjars bin/classes-processed.jar | |
| -libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar | |
| -dontpreverify | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -optimizations !code/simplification/arithmetic | |
| -keepattributes *Annotation* | |
| -keep public class * extends android.app.Activity | |
| -keep public class * extends android.app.Application | |
| -keep public class * extends android.app.Service | |
| -keep public class * extends android.content.BroadcastReceiver | |
| -keep public class * extends android.content.ContentProvider | |
| -keep public class * extends android.view.View { | |
| public <init>(android.content.Context); | |
| public <init>(android.content.Context, android.util.AttributeSet); | |
| public <init>(android.content.Context, android.util.AttributeSet, int); | |
| public void set*(...); | |
| } | |
| -keepclasseswithmembers class * { | |
| public <init>(android.content.Context, android.util.AttributeSet); | |
| } | |
| -keepclasseswithmembers class * { | |
| public <init>(android.content.Context, android.util.AttributeSet, int); | |
| } | |
| -keepclassmembers class * extends android.content.Context { | |
| public void *(android.view.View); | |
| public void *(android.view.MenuItem); | |
| } | |
| -keepclassmembers class * implements android.os.Parcelable { | |
| static ** CREATOR; | |
| } | |
| -keepclassmembers class **.R$* { | |
| public static <fields>; | |
| } | |
| -keepclassmembers class * { | |
| @android.webkit.JavascriptInterface <methods>; | |
| } | |
| </pre> | |
| <p> | |
| Most importantly, we're keeping all fundamental classes that may be referenced | |
| by the <code>AndroidManifest.xml</code> file of the application. If your | |
| manifest file contains other classes and methods, you may have to specify | |
| those as well. | |
| <p> | |
| We're keeping annotations, since they might be used by custom | |
| <code>RemoteViews</code>. | |
| <p> | |
| We're keeping any custom <code>View</code> extensions and other classes with | |
| typical constructors, since they might be referenced from XML layout files. | |
| <p> | |
| We're also keeping possible <code>onClick</code> handlers in | |
| custom <code>Context</code> extensions, since they might be referenced from | |
| XML layout files. | |
| <p> | |
| We're also keeping the required static fields in <code>Parcelable</code> | |
| implementations, since they are accessed by introspection. | |
| <p> | |
| We're keeping the static fields of referenced inner classes of auto-generated | |
| <code>R</code> classes, just in case your code is accessing those fields by | |
| introspection. Note that the compiler already inlines primitive fields, so | |
| ProGuard can generally remove all these classes entirely anyway (because the | |
| classes are not referenced and therefore not required). | |
| <p> | |
| Finally, we're keeping annotated Javascript interface methods, so they can be | |
| exported and accessed by their original names. Javascript interface methods | |
| that are not annotated (in code targeted at Android versions older than 4.2) | |
| still need to be preserved manually. | |
| <p> | |
| If you're using additional Google APIs, you'll have to specify | |
| those as well, for instance: | |
| <pre> | |
| -libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar | |
| </pre> | |
| <p> | |
| If you're using Google's optional License Verification Library, you can | |
| obfuscate its code along with your own code. You do have to preserve | |
| its <code>ILicensingService</code> interface for the library to work: | |
| <pre> | |
| -keep public interface com.android.vending.licensing.ILicensingService | |
| </pre> | |
| <p> | |
| If you're using the Android Compatibility library, you should add the | |
| following line, to let ProGuard know it's ok that the library references some | |
| classes that are not available in all versions of the API: | |
| <pre> | |
| -dontwarn android.support.** | |
| </pre> | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, | |
| <a href="#enumerations">enumerations</a>, | |
| and <a href="#resourcefiles">resource files</a>. You may also want to add | |
| options for producing <a href="#stacktrace">useful stack traces</a> and | |
| to <a href="#logging">remove logging</a>. You can find a complete sample | |
| configuration in <code>examples/android.pro</code> in the ProGuard | |
| distribution. | |
| <h3><a name="library">A typical library</a></h3> | |
| These options shrink, optimize, and obfuscate an entire library, keeping all | |
| public and protected classes and class members, native method names, and | |
| serialization code. The processed version of the library can then still be | |
| used as such, for developing code based on its public API. | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -printmapping out.map | |
| -keepparameternames | |
| -renamesourcefileattribute SourceFile | |
| -keepattributes Exceptions,InnerClasses,Signature,Deprecated, | |
| SourceFile,LineNumberTable,*Annotation*,EnclosingMethod | |
| -keep public class * { | |
| public protected *; | |
| } | |
| -keepclassmembernames class * { | |
| java.lang.Class class$(java.lang.String); | |
| java.lang.Class class$(java.lang.String, boolean); | |
| } | |
| -keepclasseswithmembernames,includedescriptorclasses class * { | |
| native <methods>; | |
| } | |
| -keepclassmembers,allowoptimization enum * { | |
| public static **[] values(); | |
| public static ** valueOf(java.lang.String); | |
| } | |
| -keepclassmembers class * implements java.io.Serializable { | |
| static final long serialVersionUID; | |
| private static final java.io.ObjectStreamField[] serialPersistentFields; | |
| private void writeObject(java.io.ObjectOutputStream); | |
| private void readObject(java.io.ObjectInputStream); | |
| java.lang.Object writeReplace(); | |
| java.lang.Object readResolve(); | |
| } | |
| </pre> | |
| <p> | |
| This configuration should preserve everything we'll ever want to access in the | |
| library. Only if there are any other non-public classes or methods that are | |
| invoked dynamically, they should be specified using additional <a | |
| href="usage.html#keep"><code>-keep</code></a> options. | |
| <p> | |
| The <a | |
| href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a> | |
| option for the <code>class$</code> methods is not strictly necessary. These | |
| methods are inserted by the <code>javac</code> compiler and the | |
| <code>jikes</code> compiler respectively, in JDK 1.2 and older, to implement | |
| the <code>.class</code> construct. ProGuard will automatically detect them and | |
| deal with them, even when their names have been obfuscated. However, other | |
| obfuscators may rely on the original method names. It may therefore be helpful | |
| to preserve them, in case these other obfuscators are ever used for further | |
| obfuscation of the library. | |
| <p> | |
| The "Exceptions" attribute has to be preserved, so the compiler knows which | |
| exceptions methods may throw. | |
| <p> | |
| The "InnerClasses" attribute (or more precisely, its source name part) has to | |
| be preserved too, for any inner classes that can be referenced from outside the | |
| library. The <code>javac</code> compiler would be unable to find the inner | |
| classes otherwise. | |
| <p> | |
| The "Signature" attribute is required to be able to access generic types when | |
| compiling in JDK 5.0 and higher. | |
| <p> | |
| The <a href="usage.html#keepparameternames"><code>-keepparameternames</code></a> | |
| option keeps the parameter names in the "LocalVariableTable" and | |
| "LocalVariableTypeTable" attributes of public library methods. Some IDEs can | |
| present these names to the developers who use the library. | |
| <p> | |
| Finally, we're keeping the "Deprecated" attribute and the attributes for | |
| producing <a href="#stacktrace">useful stack traces</a>. | |
| <p> | |
| We've also added some options for for processing <a href="#native">native | |
| methods</a>, <a href="#enumerations">enumerations</a>, <a | |
| href="#serializable">serializable classes</a>, and <a | |
| href="#annotations">annotations</a>, which are all discussed in their | |
| respective examples. | |
| <h3><a name="applications">All possible applications in the input jars</a></h3> | |
| These options shrink, optimize, and obfuscate all public applications in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -printseeds | |
| -keepclasseswithmembers public class * { | |
| public static void main(java.lang.String[]); | |
| } | |
| </pre> | |
| <p> | |
| Note the use of <a | |
| href="usage.html#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a>. | |
| We don't want to preserve all classes, just all classes that have main | |
| methods, and those methods. | |
| <p> | |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints | |
| out which classes exactly will be preserved, so we know for sure we're getting | |
| what we want. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, <a | |
| href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="applets">All possible applets in the input jars</a></h3> | |
| These options shrink, optimize, and obfuscate all public applets in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -printseeds | |
| -keep public class * extends java.applet.Applet | |
| </pre> | |
| <p> | |
| We're simply keeping all classes that extend the <code>Applet</code> class. | |
| <p> | |
| Again, the <a href="usage.html#printseeds"><code>-printseeds</code></a> option | |
| prints out which applets exactly will be preserved. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, <a | |
| href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="midlets">All possible midlets in the input jars</a></h3> | |
| These options shrink, optimize, obfuscate, and preverify all public midlets in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -microedition | |
| -printseeds | |
| -keep public class * extends javax.microedition.midlet.MIDlet | |
| </pre> | |
| <p> | |
| We're simply keeping all classes that extend the <code>MIDlet</code> class. | |
| <p> | |
| The <a href="usage.html#microedition"><code>-microedition</code></a> option | |
| makes sure the class files are preverified for Java Micro Edition, producing | |
| compact <code>StackMap</code> attributes. It is no longer necessary to run an | |
| external preverifier. | |
| <p> | |
| Be careful if you do use the external <code>preverify</code> tool on a platform | |
| with a case-insensitive filing system, such as Windows. Because this tool | |
| unpacks your processed jars, you should then use ProGuard's <a | |
| href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a> | |
| option. | |
| <p> | |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints | |
| out which midlets exactly will be preserved. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a> and <a href="#resourcefiles">resource files</a>. | |
| <p> | |
| Note that you will still have to adapt the midlet jar size in the | |
| corresponding jad file; ProGuard doesn't do that for you. | |
| <h3><a name="jcapplets">All possible Java Card applets in the input jars</a></h3> | |
| These options shrink, optimize, and obfuscate all public Java Card applets in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/javacard2.2.2/lib/api.jar | |
| -dontwarn java.lang.Class | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -printseeds | |
| -keep public class * implements javacard.framework.Applet | |
| </pre> | |
| <p> | |
| We're simply keeping all classes that implement the <code>Applet</code> | |
| interface. | |
| <p> | |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints | |
| out which applets exactly will be preserved. | |
| <h3><a name="xlets">All possible xlets in the input jars</a></h3> | |
| These options shrink, optimize, and obfuscate all public xlets in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/jtv1.1/javatv.jar | |
| -libraryjars /usr/local/java/cdc1.1/lib/cdc.jar | |
| -libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip | |
| -overloadaggressively | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| -printseeds | |
| -keep public class * implements javax.tv.xlet.Xlet | |
| </pre> | |
| <p> | |
| We're simply keeping all classes that implement the <code>Xlet</code> interface. | |
| <p> | |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints | |
| out which xlets exactly will be preserved. | |
| <h3><a name="servlets">All possible servlets in the input jars</a></h3> | |
| These options shrink, optimize, and obfuscate all public servlets in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -libraryjars /usr/local/java/servlet/servlet.jar | |
| -printseeds | |
| -keep public class * implements javax.servlet.Servlet | |
| </pre> | |
| <p> | |
| Keeping all servlets is very similar to keeping all applets. The servlet API | |
| is not part of the standard run-time jar, so we're specifying it as a library. | |
| Don't forget to use the right path name. | |
| <p> | |
| We're then keeping all classes that implement the <code>Servlet</code> | |
| interface. We're using the <code>implements</code> keyword because it looks | |
| more familiar in this context, but it is equivalent to <code>extends</code>, | |
| as far as ProGuard is concerned. | |
| <p> | |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints | |
| out which servlets exactly will be preserved. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, <a | |
| href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="scala">Scala applications with the Scala runtime</a></h3> | |
| These options shrink, optimize, and obfuscate all public Scala applications in | |
| <code>in.jar</code>: | |
| <pre> | |
| -injars in.jar | |
| -injars /usr/local/java/scala-2.9.1/lib/scala-library.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -dontwarn scala.** | |
| -keepclasseswithmembers public class * { | |
| public static void main(java.lang.String[]); | |
| } | |
| -keep class * implements org.xml.sax.EntityResolver | |
| -keepclassmembers class * { | |
| ** MODULE$; | |
| } | |
| -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool { | |
| long eventCount; | |
| int workerCounts; | |
| int runControl; | |
| scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack; | |
| scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack; | |
| } | |
| -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread { | |
| int base; | |
| int sp; | |
| int runState; | |
| } | |
| -keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask { | |
| int status; | |
| } | |
| -keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue { | |
| scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head; | |
| scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail; | |
| scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe; | |
| } | |
| </pre> | |
| <p> | |
| The configuration is essentially the same as | |
| for <a href="#applications">processing applications</a>, because Scala is | |
| compiled to ordinary Java bytecode. However, the example processes the Scala | |
| runtime library as well. The processed jar can be an order of magnitude | |
| smaller and a few times faster than the original code (for the Scala code | |
| examples, for instance). | |
| <p> | |
| The <a href="usage.html#dontwarn"><code>-dontwarn</code></a> option tells | |
| ProGuard not to complain about some artefacts in the Scala runtime, the way it | |
| is compiled by the <code>scalac</code> compiler (at least in Scala 2.9.1 and | |
| older). Note that this option should always be used with care. | |
| <p> | |
| The additional <a href="usage.html#keepoverview"><code>-keep</code></a> | |
| options make sure that some classes and some fields that are accessed by means | |
| of introspection are not removed or renamed. | |
| <p> | |
| If applicable, you should add options for processing <a href="#native">native | |
| methods</a>, <a href="#callback">callback methods</a>, <a | |
| href="#enumerations">enumerations</a>, <a href="#serializable">serializable | |
| classes</a>, <a href="#beans">bean classes</a>, <a | |
| href="#annotations">annotations</a>, and <a href="#resourcefiles">resource | |
| files</a>. | |
| <h3><a name="native">Processing native methods</a></h3> | |
| If your application, applet, servlet, library, etc., contains native methods, | |
| you'll want to preserve their names and their classes' names, so they can | |
| still be linked to the native library. The following additional option will | |
| ensure that: | |
| <pre> | |
| -keepclasseswithmembernames,includedescriptorclasses class * { | |
| native <methods>; | |
| } | |
| </pre> | |
| <p> | |
| Note the use of | |
| <a href="usage.html#keepclasseswithmembernames"><code>-keepclasseswithmembernames</code></a>. | |
| We don't want to preserve all classes or all native methods; we just want to | |
| keep the relevant names from being obfuscated. The modifier | |
| <a href="usage.html#includedescriptorclasses">includedescriptorclasses</a> | |
| additionally makes sure that the return types and parameter types aren't | |
| renamed either, so the entire signatures remain compatible with the native | |
| libraries. | |
| <p> | |
| ProGuard doesn't look at your native code, so it won't automatically preserve | |
| the classes or class members that are invoked by the native code. These are | |
| entry points, which you'll have to specify explicitly. <a | |
| href="callback">Callback methods</a> are discussed below as a typical example. | |
| <h3><a name="callback">Processing callback methods</a></h3> | |
| If your application, applet, servlet, library, etc., contains callback | |
| methods, which are called from external code (native code, scripts,...), | |
| you'll want to preserve them, and probably their classes too. They are just | |
| entry points to your code, much like, say, the main method of an application. | |
| If they aren't preserved by other <code>-keep</code> options, something like | |
| the following option will keep the callback class and method: | |
| <pre> | |
| -keep class mypackage.MyCallbackClass { | |
| void myCallbackMethod(java.lang.String); | |
| } | |
| </pre> | |
| <p> | |
| This will preserve the given class and method from being removed or renamed. | |
| <h3><a name="enumerations">Processing enumeration classes</a></h3> | |
| If your application, applet, servlet, library, etc., contains enumeration | |
| classes, you'll have to preserve some special methods. Enumerations were | |
| introduced in Java 5. The java compiler translates enumerations into classes | |
| with a special structure. Notably, the classes contain implementations of some | |
| static methods that the run-time environment accesses by introspection (Isn't | |
| that just grand? Introspection is the self-modifying code of a new | |
| generation). You have to specify these explicitly, to make sure they aren't | |
| removed or obfuscated: | |
| <pre> | |
| -keepclassmembers,allowoptimization enum * { | |
| public static **[] values(); | |
| public static ** valueOf(java.lang.String); | |
| } | |
| </pre> | |
| <h3><a name="serializable">Processing serializable classes</a></h3> | |
| More complex applications, applets, servlets, libraries, etc., may contain | |
| classes that are serialized. Depending on the way in which they are used, they | |
| may require special attention: | |
| <ul> | |
| <li>Often, serialization is simply a means of transporting data, without | |
| long-term storage. Classes that are shrunk and obfuscated should then | |
| continue to function fine with the following additional options: | |
| <pre> | |
| -keepclassmembers class * implements java.io.Serializable { | |
| private static final java.io.ObjectStreamField[] serialPersistentFields; | |
| private void writeObject(java.io.ObjectOutputStream); | |
| private void readObject(java.io.ObjectInputStream); | |
| java.lang.Object writeReplace(); | |
| java.lang.Object readResolve(); | |
| } | |
| </pre> | |
| <p> | |
| The <a | |
| href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a> | |
| option makes sure that any serialization methods are kept. By using this | |
| option instead of the basic <code>-keep</code> option, we're not | |
| forcing preservation of <i>all</i> serializable classes, just preservation | |
| of the listed members of classes that are actually used.</li> | |
| <li>Sometimes, the serialized data are stored, and read back later into newer | |
| versions of the serializable classes. One then has to take care the classes | |
| remain compatible with their unprocessed versions and with future | |
| processed versions. In such cases, the relevant classes will most likely | |
| have <code>serialVersionUID</code> fields. The following options should | |
| then be sufficient to ensure compatibility over time: | |
| <pre> | |
| -keepnames class * implements java.io.Serializable | |
| -keepclassmembers class * implements java.io.Serializable { | |
| static final long serialVersionUID; | |
| private static final java.io.ObjectStreamField[] serialPersistentFields; | |
| !static !transient <fields>; | |
| private void writeObject(java.io.ObjectOutputStream); | |
| private void readObject(java.io.ObjectInputStream); | |
| java.lang.Object writeReplace(); | |
| java.lang.Object readResolve(); | |
| } | |
| </pre> | |
| <p> | |
| The <code>serialVersionUID</code> and <code>serialPersistentFields</code> | |
| lines makes sure those fields are preserved, if they are present. | |
| The <code><fields></code> line preserves all non-static, | |
| non-transient fields, with their original names. The introspection of the | |
| serialization process and the de-serialization process will then find | |
| consistent names.</li> | |
| <li>Occasionally, the serialized data have to remain compatible, but the | |
| classes involved lack <code>serialVersionUID</code> fields. I imagine the | |
| original code will then be hard to maintain, since the serial version UID | |
| is then computed from a list of features the serializable class. Changing | |
| the class ever so slightly may change the computed serial version UID. The | |
| list of features is specified in the section on <a | |
| href="http://docs.oracle.com/javase/8/docs/platform/serialization/spec/class.html#a4100">Stream | |
| Unique Identifiers</a> of Sun's <a | |
| href="http://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html">Java | |
| Object Serialization Specification</a>. The following directives should at | |
| least partially ensure compatibility with the original classes: | |
| <pre> | |
| -keepnames class * implements java.io.Serializable | |
| -keepclassmembers class * implements java.io.Serializable { | |
| static final long serialVersionUID; | |
| private static final java.io.ObjectStreamField[] serialPersistentFields; | |
| !static !transient <fields>; | |
| !private <fields>; | |
| !private <methods>; | |
| private void writeObject(java.io.ObjectOutputStream); | |
| private void readObject(java.io.ObjectInputStream); | |
| java.lang.Object writeReplace(); | |
| java.lang.Object readResolve(); | |
| } | |
| </pre> | |
| <p> | |
| The new options force preservation of the elements involved in the UID | |
| computation. In addition, the user will have to manually specify all | |
| interfaces of the serializable classes (using something like "<code>-keep | |
| interface MyInterface</code>"), since these names are also used when | |
| computing the UID. A fast but sub-optimal alternative would be simply | |
| keeping all interfaces with "<code>-keep interface *</code>".</li> | |
| <li>In the rare event that you are serializing lambda expressions in Java 8 or | |
| higher, you need to preserve some methods and adapt the hard-coded names | |
| of the classes in which they occur: | |
| <pre> | |
| -keepclassmembers class * { | |
| private static synthetic java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda); | |
| } | |
| -keepclassmembernames class * { | |
| private static synthetic *** lambda$*(...); | |
| } | |
| -adaptclassstrings com.example.Test | |
| </pre> | |
| <p> | |
| This should satisfy the reflection in the deserialization code of the | |
| Java run-time. | |
| </ul> | |
| <p> | |
| Note that the above options may preserve more classes and class members | |
| than strictly necessary. For instance, a large number of classes may implement | |
| the <code>Serialization</code> interface, yet only a small number may actually | |
| ever be serialized. Knowing your application and tuning the configuration | |
| often produces more compact results. | |
| <h3><a name="beans">Processing bean classes</a></h3> | |
| If your application, applet, servlet, library, etc., makes extensive use of | |
| introspection on bean classes to find bean editor classes, or getter and | |
| setter methods, then configuration may become painful. There's not much else | |
| you can do than making sure the bean class names, or the getter and setter | |
| names don't change. For instance: | |
| <pre> | |
| -keep public class mypackage.MyBean { | |
| public void setMyProperty(int); | |
| public int getMyProperty(); | |
| } | |
| -keep public class mypackage.MyBeanEditor | |
| </pre> | |
| <p> | |
| If there are too many elements to list explicitly, wildcards in class names | |
| and method signatures might be helpful. This example preserves all possible | |
| setters and getters in classes in the package <code>mybeans</code>: | |
| <pre> | |
| -keep class mybeans.** { | |
| void set*(***); | |
| void set*(int, ***); | |
| boolean is*(); | |
| boolean is*(int); | |
| *** get*(); | |
| *** get*(int); | |
| } | |
| </pre> | |
| <p> | |
| The '<code>***</code>' wildcard matches any type (primitive or non-primitive, | |
| array or non-array). The methods with the '<code>int</code>' arguments matches | |
| properties that are lists. | |
| <h3><a name="annotations">Processing annotations</a></h3> | |
| If your application, applet, servlet, library, etc., uses annotations, you may | |
| want to preserve them in the processed output. Annotations are represented by | |
| attributes that have no direct effect on the execution of the code. However, | |
| their values can be retrieved through introspection, allowing developers to | |
| adapt the execution behavior accordingly. By default, ProGuard treats | |
| annotation attributes as optional, and removes them in the obfuscation step. | |
| If they are required, you'll have to specify this explicitly: | |
| <pre> | |
| -keepattributes *Annotation* | |
| </pre> | |
| <p> | |
| For brevity, we're specifying a wildcarded attribute name, which will match | |
| <code>RuntimeVisibleAnnotations</code>, | |
| <code>RuntimeInvisibleAnnotations</code>, | |
| <code>RuntimeVisibleParameterAnnotations</code>, | |
| <code>RuntimeInvisibleParameterAnnotations</code>, and | |
| <code>AnnotationDefault</code>. Depending on the purpose of the processed | |
| code, you could refine this selection, for instance not keeping the run-time | |
| invisible annotations (which are only used at compile-time). | |
| <p> | |
| Some code may make further use of introspection to figure out the enclosing | |
| methods of anonymous inner classes. In that case, the corresponding attribute | |
| has to be preserved as well: | |
| <pre> | |
| -keepattributes EnclosingMethod | |
| </pre> | |
| <h3><a name="database">Processing database drivers</a></h3> | |
| Database drivers are implementations of the <code>Driver</code> interface. | |
| Since they are often created dynamically, you may want to preserve any | |
| implementations that you are processing as entry points: | |
| <pre> | |
| -keep class * implements java.sql.Driver | |
| </pre> | |
| <p> | |
| This option also gets rid of the note that ProGuard prints out about | |
| <code>(java.sql.Driver)Class.forName</code> constructs, if you are | |
| instantiating a driver in your code (without necessarily implementing any | |
| drivers yourself). | |
| <h3><a name="componentui">Processing ComponentUI classes</a></h3> | |
| Swing UI look and feels are implemented as extensions of the | |
| <code>ComponentUI</code> class. For some reason, these have to contain a | |
| static method <code>createUI</code>, which the Swing API invokes using | |
| introspection. You should therefore always preserve the method as an entry | |
| point, for instance like this: | |
| <pre> | |
| -keep class * extends javax.swing.plaf.ComponentUI { | |
| public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent); | |
| } | |
| </pre> | |
| <p> | |
| This option also keeps the classes themselves. | |
| <h3><a name="rmi">Processing RMI code</a></h3> | |
| Reportedly, the easiest way to handle RMI code is to process the code with | |
| ProGuard first and then invoke the <code>rmic</code> tool. If that is not | |
| possible, you may want to try something like this: | |
| <pre> | |
| -keepattributes Exceptions | |
| -keep interface * extends java.rmi.Remote { | |
| <methods>; | |
| } | |
| -keep class * implements java.rmi.Remote { | |
| <init>(java.rmi.activation.ActivationID, java.rmi.MarshalledObject); | |
| } | |
| </pre> | |
| <p> | |
| The first <code>-keep</code> option keeps all your Remote interfaces and their | |
| methods. The second one keeps all the implementations, along with their | |
| particular RMI constructors, if any. | |
| <p> | |
| The <code>Exceptions</code> attribute has to be kept too, because the RMI | |
| handling code performs introspection to check whether the method signatures | |
| are compatible. | |
| <h3><a name="injection">Processing dependency injection</a></h3> | |
| If your application is using JEE-style dependency injection, the application | |
| container will automatically assign instances of resource classes to fields and | |
| methods that are annotated with <code>@Resource</code>. The container applies | |
| introspection, even accessing private class members directly. It typically | |
| constructs a resource name based on the type name and the class member name. | |
| We then have to avoid that such class members are removed or renamed: | |
| <pre> | |
| -keepclassmembers class * { | |
| @javax.annotation.Resource *; | |
| } | |
| </pre> | |
| <p> | |
| The Spring framework has another similar annotation <code>@Autowired</code>: | |
| <pre> | |
| -keepclassmembers class * { | |
| @org.springframework.beans.factory.annotation.Autowired *; | |
| } | |
| </pre> | |
| <h3><a name="dagger">Processing Dagger code</a></h3> | |
| If your Android application includes Dagger for dependency injection, you need | |
| a few lines of configuration, since Dagger heavily relies on reflection to tie | |
| together the code at runtime. You need to preserve the annotated class | |
| members, the generated classes, and a utility class: | |
| <pre> | |
| -keepclassmembers,allowobfuscation class * { | |
| @dagger.** *; | |
| } | |
| -keep class **$$ModuleAdapter | |
| -keep class **$$InjectAdapter | |
| -keep class **$$StaticInjection | |
| -keepnames class dagger.Lazy | |
| </pre> | |
| <p> | |
| Unfortunately, you still need to explicitly preserve the corresponding base | |
| classes from your project. For example, for a generated class like | |
| <code>com.example.SomeClass$$ModuleAdapter</code>, you still need to specify: | |
| <pre> | |
| -keep class com.example.SomeClass | |
| </pre> | |
| <p> | |
| Dagger can then still combine the corresponding pairs of classes, based on | |
| their names. You can figure out the base classes by listing the generated | |
| classes in the <code>gen</code> directory of your project (e.g. | |
| <code>com/examples/SomeClass$$ModuleAdapter.class</code>). | |
| <p> | |
| Dagger 2 no longer relies on reflection with these naming conventions, which | |
| makes life a lot easier. | |
| <h3><a name="butterknife">Processing Butterknife code</a></h3> | |
| If your Android application includes Butterknife to inject views, you also | |
| need a few lines of configuration, since Butterknife relies on reflection to | |
| tie together the code at runtime: | |
| <pre> | |
| -keep @interface butterknife.* | |
| -keepclasseswithmembers class * { | |
| @butterknife.* <fields>; | |
| } | |
| -keepclasseswithmembers class * { | |
| @butterknife.* <methods>; | |
| } | |
| -keepclasseswithmembers class * { | |
| @butterknife.On* <methods>; | |
| } | |
| -keep class **$$ViewInjector { | |
| public static void inject(...); | |
| public static void reset(...); | |
| } | |
| -keep class **$$ViewBinder { | |
| public static void bind(...); | |
| public static void unbind(...); | |
| } | |
| </pre> | |
| <p> | |
| These settings preserve the Butterknife annotations, the annotated fields and | |
| methods, and the generated classes and methods that Butterknife accesses by | |
| reflection. | |
| <h3><a name="resourcefiles">Processing resource files</a></h3> | |
| If your application, applet, servlet, library, etc., contains resource files, | |
| it may be necessary to adapt their names and/or their contents when the | |
| application is obfuscated. The following two options can achieve this | |
| automatically: | |
| <pre> | |
| -adaptresourcefilenames **.properties,**.gif,**.jpg | |
| -adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF | |
| </pre> | |
| <p> | |
| The <a href="usage.html#adaptresourcefilenames">-adaptresourcefilenames</a> | |
| option in this case renames properties files and image files in the processed | |
| output, based on the obfuscated names of their corresponding class files (if | |
| any). The <a | |
| href="usage.html#adaptresourcefilecontents">-adaptresourcefilecontents</a> | |
| option looks for class names in properties files and in the manifest file, and | |
| replaces these names by the obfuscated names (if any). You'll probably want to | |
| adapt the filters to suit your application. | |
| <h3><a name="manifestfiles">Processing manifest files</a></h3> | |
| As illustrated in the previous section, manifest files can be treated like | |
| ordinary resource files. ProGuard can adapt obfuscated class names in the | |
| files, but it won't make any other changes. If you want anything else, you | |
| should apply an external tool. For instance, if a manifest file contains | |
| signing information, you should sign the jar again after it has been | |
| processed. | |
| <p> | |
| If you're merging several input jars into a single output jar, you'll have to | |
| pick one, typically by specifying <a href="usage.html#filters">filters</a>: | |
| <pre> | |
| -injars in1.jar | |
| -injars in2.jar(!META-INF/MANIFEST.MF) | |
| -injars in3.jar(!META-INF/MANIFEST.MF) | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| The filters will let ProGuard copy the manifest file from the first jar and | |
| ignore any manifest files in the second and third input jars. Note that | |
| ProGuard will leave the order of the files in the jars unchanged; manifest | |
| files are not necessarily put first. | |
| <h3><a name="stacktrace">Producing useful obfuscated stack traces</a></h3> | |
| These options let obfuscated applications or libraries produce stack traces | |
| that can still be deciphered later on: | |
| <pre> | |
| -printmapping out.map | |
| -renamesourcefileattribute SourceFile | |
| -keepattributes SourceFile,LineNumberTable | |
| </pre> | |
| <p> | |
| We're keeping all source file attributes, but we're replacing their values by | |
| the string "SourceFile". We could use any string. This string is already | |
| present in all class files, so it doesn't take up any extra space. If you're | |
| working with J++, you'll want to keep the "SourceDir" attribute as well. | |
| <p> | |
| We're also keeping the line number tables of all methods. | |
| <p> | |
| Whenever both of these attributes are present, the Java run-time environment | |
| will include line number information when printing out exception stack traces. | |
| <p> | |
| The information will only be useful if we can map the obfuscated names back to | |
| their original names, so we're saving the mapping to a file | |
| <code>out.map</code>. The information can then be used by the <a | |
| href="retrace/index.html">ReTrace</a> tool to restore the original stack trace. | |
| <h3><a name="repackaging">Obfuscating package names</a></h3> | |
| Package names can be obfuscated in various ways, with increasing levels of | |
| obfuscation and compactness. For example, consider the following classes: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| mycompany.myapplication.Foo | |
| mycompany.myapplication.Bar | |
| mycompany.myapplication.extra.FirstExtra | |
| mycompany.myapplication.extra.SecondExtra | |
| mycompany.util.FirstUtil | |
| mycompany.util.SecondUtil | |
| </pre> | |
| <p> | |
| Let's assume the class name <code>mycompany.myapplication.MyMain</code> is the | |
| main application class that is kept by the configuration. All other class names | |
| can be obfuscated. | |
| <p> | |
| By default, packages that contain classes that can't be renamed aren't renamed | |
| either, and the package hierarchy is preserved. This results in obfuscated | |
| class names like these: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| mycompany.myapplication.a | |
| mycompany.myapplication.b | |
| mycompany.myapplication.a.a | |
| mycompany.myapplication.a.b | |
| mycompany.a.a | |
| mycompany.a.b | |
| </pre> | |
| <p> | |
| The <a | |
| href="usage.html#flattenpackagehierarchy"><code>-flattenpackagehierarchy</code></a> | |
| option obfuscates the package names further, by flattening the package | |
| hierarchy of obfuscated packages: | |
| <pre> | |
| -flattenpackagehierarchy 'myobfuscated' | |
| </pre> | |
| <p> | |
| The obfuscated class names then look as follows: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| mycompany.myapplication.a | |
| mycompany.myapplication.b | |
| myobfuscated.a.a | |
| myobfuscated.a.b | |
| myobfuscated.b.a | |
| myobfuscated.b.b | |
| </pre> | |
| <p> | |
| Alternatively, the <a | |
| href="usage.html#repackageclasses"><code>-repackageclasses</code></a> option | |
| obfuscates the entire packaging, by combining obfuscated classes into a single | |
| package: | |
| <pre> | |
| -repackageclasses 'myobfuscated' | |
| </pre> | |
| The obfuscated class names then look as follows: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| mycompany.myapplication.a | |
| mycompany.myapplication.b | |
| myobfuscated.a | |
| myobfuscated.b | |
| myobfuscated.c | |
| myobfuscated.d | |
| </pre> | |
| <p> | |
| Additionally specifying the <a | |
| href="usage.html#allowaccessmodification"><code>-allowaccessmodification</code></a> | |
| option allows access permissions of classes and class members to | |
| be broadened, opening up the opportunity to repackage all obfuscated classes: | |
| <pre> | |
| -repackageclasses 'myobfuscated' | |
| -allowaccessmodification | |
| </pre> | |
| The obfuscated class names then look as follows: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| myobfuscated.a | |
| myobfuscated.b | |
| myobfuscated.c | |
| myobfuscated.d | |
| myobfuscated.e | |
| myobfuscated.f | |
| </pre> | |
| <p> | |
| The specified target package can always be the root package. For instance: | |
| <pre> | |
| -repackageclasses '' | |
| -allowaccessmodification | |
| </pre> | |
| The obfuscated class names are then the shortest possible names: | |
| <pre> | |
| mycompany.myapplication.MyMain | |
| a | |
| b | |
| c | |
| d | |
| e | |
| f | |
| </pre> | |
| <p> | |
| Note that not all levels of obfuscation of package names may be acceptable for | |
| all code. Notably, you may have to take into account that your application may | |
| contain <a href="#resourcefiles">resource files</a> that have to be adapted. | |
| <h3><a name="logging">Removing logging code</a></h3> | |
| You can let ProGuard remove logging code. The trick is to specify that the | |
| logging methods don't have side-effects — even though they actually do, | |
| since they write to the console or to a log file. ProGuard will take your word | |
| for it and remove the invocations (in the optimization step) and if possible | |
| the logging classes and methods themselves (in the shrinking step). | |
| <p> | |
| For example, this configuration removes invocations of the Android logging | |
| methods: | |
| <pre> | |
| -assumenosideeffects class android.util.Log { | |
| public static boolean isLoggable(java.lang.String, int); | |
| public static int v(...); | |
| public static int i(...); | |
| public static int w(...); | |
| public static int d(...); | |
| public static int e(...); | |
| } | |
| </pre> | |
| <p> | |
| The wildcards are a shortcut to match all versions of the methods. Be careful | |
| not to use a <code>*</code> wildcard to match all methods, because it would | |
| also match methods like <code>wait()</code>, higher up the hierarchy. Removing | |
| those invocations will generally break your code. | |
| <p> | |
| Note that you generally can't remove logging code that uses | |
| <code>System.out.println</code>, since you would be removing all invocations | |
| of <code>java.io.PrintStream#println</code>, which could break your | |
| application. You can work around it by creating your own logging methods and | |
| let ProGuard remove those. | |
| <h3><a name="restructuring">Restructuring the output archives</a></h3> | |
| In simple applications, all output classes and resources files are merged into | |
| a single jar. For example: | |
| <pre> | |
| -injars classes | |
| -injars in1.jar | |
| -injars in2.jar | |
| -injars in3.jar | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| This configuration merges the processed versions of the files in the | |
| <code>classes</code> directory and the three jars into a single output jar | |
| <code>out.jar</code>. | |
| <p> | |
| If you want to preserve the structure of your input jars (and/or wars, ears, | |
| zips, or directories), you can specify an output directory (or a war, an ear, | |
| or a zip). For example: | |
| <pre> | |
| -injars in1.jar | |
| -injars in2.jar | |
| -injars in3.jar | |
| -outjars out | |
| </pre> | |
| <p> | |
| The input jars will then be reconstructed in the directory <code>out</code>, | |
| with their original names. | |
| <p> | |
| You can also combine archives into higher level archives. For example: | |
| <pre> | |
| -injars in1.jar | |
| -injars in2.jar | |
| -injars in3.jar | |
| -outjars out.war | |
| </pre> | |
| <p> | |
| The other way around, you can flatten the archives inside higher level | |
| archives into simple archives: | |
| <pre> | |
| -injars in.war | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| This configuration puts the processed contents of all jars inside | |
| <code>in.war</code> (plus any other contents of <code>in.war</code>) into | |
| <code>out.jar</code>. | |
| <p> | |
| If you want to combine input jars (and/or wars, ears, zips, or directories) | |
| into output jars (and/or wars, ears, zips, or directories), you can group the | |
| <a href="usage.html#injars"><code>-injars</code></a> and <a | |
| href="usage.html#outjars"><code>-outjars</code></a> options. For example: | |
| <pre> | |
| -injars base_in1.jar | |
| -injars base_in2.jar | |
| -injars base_in3.jar | |
| -outjars base_out.jar | |
| -injars extra_in.jar | |
| -outjars extra_out.jar | |
| </pre> | |
| <p> | |
| This configuration puts the processed results of all <code>base_in*.jar</code> | |
| jars into <code>base_out.jar</code>, and the processed results of the | |
| <code>extra_in.jar</code> into <code>extra_out.jar</code>. Note that only the | |
| order of the options matters; the additional whitespace is just for clarity. | |
| <p> | |
| This grouping, archiving, and flattening can be arbitrarily complex. ProGuard | |
| always tries to package output archives in a sensible way, reconstructing the | |
| input entries as much as required. | |
| <h3><a name="filtering">Filtering the input and the output</a></h3> | |
| If you want even greater control, you can add | |
| <a href="usage.html#filters">filters</a> to the input and the output, | |
| filtering out zips, ears, wars, jars, and/or ordinary files. For example, if | |
| you want to disregard certain files from an input jar: | |
| <pre> | |
| -injars in.jar(!images/**) | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| This configuration removes any files in the <code>images</code> directory and | |
| its subdirectories. | |
| <p> | |
| Such filters can be convenient for avoiding warnings about duplicate files in | |
| the output. For example, only keeping the manifest file from a first input jar: | |
| <pre> | |
| -injars in1.jar | |
| -injars in2.jar(!META-INF/MANIFEST.MF) | |
| -injars in3.jar(!META-INF/MANIFEST.MF) | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| Another useful application is speeding up the processing by ProGuard, by | |
| disregarding a large number of irrelevant classes in the runtime library jar: | |
| <pre> | |
| -libraryjars <java.home>/lib/rt.jar(java/**,javax/**) | |
| </pre> | |
| <p> | |
| The filter makes ProGuard disregard <code>com.sun.**</code> classes, for | |
| instance , which don't affect the processing of ordinary applications. | |
| <p> | |
| It is also possible to filter the jars (and/or wars, ears, zips) themselves, | |
| based on their names. For example: | |
| <pre> | |
| -injars in(**/acme_*.jar;) | |
| -outjars out.jar | |
| </pre> | |
| <p> | |
| Note the semi-colon in the filter; the filter in front of it applies to jar | |
| names. In this case, only <code>acme_*.jar</code> jars are read from the | |
| directory <code>in</code> and its subdirectories. Filters for war names, ear | |
| names, and zip names can be prefixed with additional semi-colons. All types of | |
| filters can be combined. They are orthogonal. | |
| <p> | |
| On the other hand, you can also filter the output, in order to control what | |
| content goes where. For example: | |
| <pre> | |
| -injars in.jar | |
| -outjars code_out.jar(**.class) | |
| -outjars resources_out.jar | |
| </pre> | |
| <p> | |
| This configuration splits the processed output, sending <code>**.class</code> | |
| files to <code>code_out.jar</code>, and all remaining files to | |
| <code>resources_out.jar</code>. | |
| <p> | |
| Again, the filtering can be arbitrarily complex, especially when combined with | |
| grouping input and output. | |
| <h3><a name="multiple">Processing multiple applications at once</a></h3> | |
| You can process several dependent or independent applications (or applets, | |
| midlets,...) in one go, in order to save time and effort. ProGuard's input and | |
| output handling offers various ways to keep the output nicely structured. | |
| <p> | |
| The easiest way is to specify your input jars (and/or wars, ears, zips, and | |
| directories) and a single output directory. ProGuard will then reconstruct the | |
| input in this directory, using the original jar names. For example, showing | |
| just the input and output options: | |
| <pre> | |
| -injars application1.jar | |
| -injars application2.jar | |
| -injars application3.jar | |
| -outjars processed_applications | |
| </pre> | |
| <p> | |
| After processing, the directory <code>processed_applications</code> will | |
| contain processed versions of application jars, with their original names. | |
| <h3><a name="incremental">Incremental obfuscation</a></h3> | |
| After having <a href="#application">processed an application</a>, e.g. | |
| ProGuard itself, you can still incrementally add other pieces of code that | |
| depend on it, e.g. the ProGuard GUI: | |
| <pre> | |
| -injars proguardgui.jar | |
| -outjars proguardgui_out.jar | |
| -injars proguard.jar | |
| -outjars proguard_out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -applymapping proguard.map | |
| -keep public class proguard.gui.ProGuardGUI { | |
| public static void main(java.lang.String[]); | |
| } | |
| </pre> | |
| <p> | |
| We're reading both unprocessed jars as input. Their processed contents will go | |
| to the respective output jars. The <a | |
| href="usage.html#applymapping"><code>-applymapping</code></a> option then | |
| makes sure the ProGuard part of the code gets the previously produced | |
| obfuscation mapping. The final application will consist of the obfuscated | |
| ProGuard jar and the additional obfuscated GUI jar. | |
| <p> | |
| The added code in this example is straightforward; it doesn't affect the | |
| original code. The <code>proguard_out.jar</code> will be identical to the one | |
| produced in the initial processing step. If you foresee adding more complex | |
| extensions to your code, you should specify the options <a | |
| href="usage.html#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>, | |
| <a href="usage.html#dontshrink"><code>-dontshrink</code></a>, and <a | |
| href="usage.html#dontoptimize"><code>-dontoptimize</code></a> <i>in the | |
| original processing step</i>. These options ensure that the obfuscated base | |
| jar will always remain usable without changes. You can then specify the base | |
| jar as a library jar: | |
| <pre> | |
| -injars proguardgui.jar | |
| -outjars proguardgui_out.jar | |
| -libraryjars proguard.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -applymapping proguard.map | |
| -keep public class proguard.gui.ProGuardGUI { | |
| public static void main(java.lang.String[]); | |
| } | |
| </pre> | |
| <h3><a name="microedition">Preverifying class files for Java Micro Edition</a></h3> | |
| Even if you're not interested in shrinking, optimizing, and obfuscating your | |
| midlets, as shown in the <a href="#midlets">midlets example</a>, you can still | |
| use ProGuard to preverify the class files for Java Micro Edition. ProGuard | |
| produces slightly more compact results than the traditional external | |
| preverifier. | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/midpapi20.jar | |
| -libraryjars /usr/local/java/wtk2.5.2/lib/cldcapi11.jar | |
| -dontshrink | |
| -dontoptimize | |
| -dontobfuscate | |
| -microedition | |
| </pre> | |
| <p> | |
| We're not processing the input, just making sure the class files are | |
| preverified by targeting them at Java Micro Edition with the <a | |
| href="usage.html#microedition"><code>-microedition</code></a> option. Note | |
| that we don't need any <code>-keep</code> options to specify entry points; all | |
| class files are simply preverified. | |
| <h3><a name="upgrade">Upgrading class files to Java 6</a></h3> | |
| The following options upgrade class files to Java 6, by updating their | |
| internal version numbers and preverifying them. The class files can then be | |
| loaded more efficiently by the Java 6 Virtual Machine. | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -dontshrink | |
| -dontoptimize | |
| -dontobfuscate | |
| -target 1.6 | |
| </pre> | |
| <p> | |
| We're not processing the input, just retargeting the class files with the <a | |
| href="usage.html#target"><code>-target</code></a> option. They will | |
| automatically be preverified for Java 6 as a result. Note that we don't need | |
| any <code>-keep</code> options to specify entry points; all class files are | |
| simply updated and preverified. | |
| <h3><a name="deadcode">Finding dead code</a></h3> | |
| These options list unused classes, fields, and methods in the application | |
| <code>mypackage.MyApplication</code>: | |
| <pre> | |
| -injars in.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -dontoptimize | |
| -dontobfuscate | |
| -dontpreverify | |
| -printusage | |
| -keep public class mypackage.MyApplication { | |
| public static void main(java.lang.String[]); | |
| } | |
| </pre> | |
| <p> | |
| We're not specifying an output jar, just printing out some results. We're | |
| saving some processing time by skipping the other processing steps. | |
| <p> | |
| The java compiler inlines primitive constants and String constants | |
| (<code>static final</code> fields). ProGuard would therefore list such fields | |
| as not being used in the class files that it analyzes, even if they <i>are</i> | |
| used in the source files. We can add a <a | |
| href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a> option | |
| that keeps those fields a priori, in order to avoid having them listed: | |
| <pre> | |
| -keepclassmembers class * { | |
| static final % *; | |
| static final java.lang.String *; | |
| } | |
| </pre> | |
| <h3><a name="structure">Printing out the internal structure of class files</a></h3> | |
| These options print out the internal structure of all class files in the input | |
| jar: | |
| <pre> | |
| -injars in.jar | |
| -dontshrink | |
| -dontoptimize | |
| -dontobfuscate | |
| -dontpreverify | |
| -dump | |
| </pre> | |
| <p> | |
| Note how we don't need to specify the Java run-time jar, because we're not | |
| processing the input jar at all. | |
| <h3><a name="annotated">Using annotations to configure ProGuard</a></h3> | |
| The traditional ProGuard configuration allows to keep a clean separation | |
| between the code and the configuration for shrinking, optimization, and | |
| obfuscation. However, it is also possible to define specific annotations, | |
| and then annotate the code to configure the processing. | |
| <p> | |
| You can find a set of such predefined annotations in the directory | |
| <code>examples/annotations/lib</code> in the ProGuard distribution. | |
| The annotation classes are defined in <code>annotations.jar</code>. The | |
| corresponding ProGuard configuration (or meta-configuration, if you prefer) | |
| is specified in <code>annotations.pro</code>. With these files, you can start | |
| annotating your code. For instance, a java source file | |
| <code>Application.java</code> can be annotated as follows: | |
| <pre> | |
| @KeepApplication | |
| public class Application { | |
| .... | |
| } | |
| </pre> | |
| <p> | |
| The ProGuard configuration file for the application can then be simplified by | |
| leveraging off these annotations: | |
| <pre> | |
| -injars in.jar | |
| -outjars out.jar | |
| -libraryjars <java.home>/lib/rt.jar | |
| -include lib/annotations.pro | |
| </pre> | |
| <p> | |
| The annotations are effectively replacing the application-dependent | |
| <code>-keep</code> options. You may still wish to add traditional | |
| <code>-keep</code> options for processing <a href="#native">native | |
| methods</a>, <a href="#enumerations">enumerations</a>, <a | |
| href="#serializable">serializable classes</a>, and <a | |
| href="#annotations">annotations</a>. | |
| <p> | |
| The directory <code>examples/annotations</code> contains more examples that | |
| illustrate some of the possibilities. | |
| <hr /> | |
| <address> | |
| Copyright © 2002-2017 | |
| <a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.guardsquare.com/">GuardSquare</a>. | |
| </address> | |
| </body> | |
| </html> |