| <!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//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> |
| |
| <h2>Examples</h2> |
| |
| Some typical useful configurations: |
| <ol> |
| <li><a href="#application">A typical application</a> |
| <li><a href="#applet">A typical applet</a> |
| <li><a href="#midlet">A typical midlet</a> |
| <li><a href="#jcapplet">A typical Java Card applet</a> |
| <li><a href="#xlet">A typical xlet</a> |
| <li><a href="#androidapplication">A typical Android application</a> |
| <li><a href="#library">A typical library</a> |
| <li><a href="#applications">All possible applications in the input jars</a> |
| <li><a href="#applets">All possible applets in the input jars</a> |
| <li><a href="#midlets">All possible midlets in the input jars</a> |
| <li><a href="#jcapplets">All possible Java Card applets in the input jars</a> |
| <li><a href="#xlets">All possible xlets in the input jars</a> |
| <li><a href="#androidapplications">All possible Android applications in the input jars</a> |
| <li><a href="#servlets">All possible servlets in the input jars</a> |
| <li><a href="#native">Processing native methods</a> |
| <li><a href="#callback">Processing callback methods</a> |
| <li><a href="#enumerations">Processing enumeration classes</a> |
| <li><a href="#serializable">Processing serializable classes</a> |
| <li><a href="#beans">Processing bean classes</a> |
| <li><a href="#annotations">Processing annotations</a> |
| <li><a href="#database">Processing database drivers</a> |
| <li><a href="#componentui">Processing ComponentUI classes</a> |
| <li><a href="#rmi">Processing RMI code</a> |
| <li><a href="#resourcefiles">Processing resource files</a> |
| <li><a href="#stacktrace">Producing useful obfuscated stack traces</a> |
| <li><a href="#repackaging">Obfuscating package names</a> |
| <li><a href="#restructuring">Restructuring the output archives</a> |
| <li><a href="#filtering">Filtering the input and the output</a> |
| <li><a href="#multiple">Processing multiple applications at once</a> |
| <li><a href="#incremental">Incremental obfuscation</a> |
| <li><a href="#microedition">Preverifying class files for Java Micro Edition</a> |
| <li><a href="#upgrade">Upgrading class files to Java 6</a> |
| <li><a href="#deadcode">Finding dead code</a> |
| <li><a href="#structure">Printing out the internal structure of class files</a> |
| <li><a href="#annotated">Using annotations to configure ProGuard</a> |
| </ol> |
| |
| You can find some sample configuration files in the <code>examples</code> |
| directory of the ProGuard distribution. |
| |
| <a name="application"> </a> |
| <h3>A typical application</h3> |
| To shrink, optimize, and obfuscate the ProGuard application itself, one would |
| typically create a configuration file <code>proguard.pro</code> and then type: |
| <pre> |
| java -jar proguard.jar @proguard.pro |
| </pre> |
| <p> |
| The configuration file would contain the following options: |
| <pre> |
| -injars proguard.jar |
| -outjars proguard_out.jar |
| -libraryjars <java.home>/lib/rt.jar |
| -printmapping proguard.map |
| |
| -keep public class proguard.ProGuard { |
| public static void main(java.lang.String[]); |
| } |
| </pre> |
| <p> |
| Note the use of the <code><java.home></code> system property; it is |
| replaced automatically. |
| <p> |
| Also note that all type names are fully specified: |
| <code>proguard.ProGuard</code> and <code>java.lang.String[]</code>. |
| <p> |
| 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> |
| 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>. For processing 'simple' applications like ProGuard, that is not |
| required. |
| |
| <a name="applet"> </a> |
| <h3>A typical applet</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>. |
| |
| <a name="midlet"> </a> |
| <h3>A typical midlet</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.1/lib/midpapi20.jar |
| -libraryjars /usr/local/java/wtk2.1/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. |
| |
| <a name="jcapplet"> </a> |
| <h3>A typical Java Card applet</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. |
| |
| <a name="xlet"> </a> |
| <h3>A typical xlet</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. |
| |
| <a name="androidapplication"> </a> |
| <h3>A typical Android application</h3> |
| These options shrink, optimize, and obfuscate the simple Android application |
| based on a single activity <code>mypackage.MyActivity</code>: |
| <pre> |
| -injars in.jar |
| -outjars out.jar |
| -libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar |
| -overloadaggressively |
| -repackageclasses '' |
| -allowaccessmodification |
| -optimizations !code/simplification/arithmetic |
| |
| -keep public class mypackage.MyActivity |
| </pre> |
| <p> |
| The configuration is very similar to the configuration for midlets, except that |
| it now targets the Android run-time environment. |
| <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. |
| <p> |
| If applicable, you should add options for processing <a href="#native">native |
| methods</a>, <a href="#callback">callback methods</a>, and <a |
| href="#resourcefiles">resource files</a>. |
| |
| <a name="library"> </a> |
| <h3>A typical library</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: |
| <pre> |
| -injars in.jar |
| -outjars out.jar |
| -libraryjars <java.home>/lib/rt.jar |
| -printmapping out.map |
| |
| -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 class * { |
| native <methods>; |
| } |
| |
| -keepclassmembers enum * { |
| public static **[] values(); |
| public static ** valueOf(java.lang.String); |
| } |
| |
| -keepclassmembers class * implements java.io.Serializable { |
| static final long serialVersionUID; |
| 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, to implement the <code>.class</code> |
| construct. ProGuard will automatically detect them and deal with them, even |
| when their names have been obfuscated. However, older versions of ProGuard and |
| 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> |
| 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. |
| |
| <a name="applications"> </a> |
| <h3>All possible applications in the input jars</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>. |
| |
| <a name="applets"> </a> |
| <h3>All possible applets in the input jars</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>. |
| |
| <a name="midlets"> </a> |
| <h3>All possible midlets in the input jars</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.1/lib/midpapi20.jar |
| -libraryjars /usr/local/java/wtk2.1/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. |
| |
| <a name="jcapplets"> </a> |
| <h3>All possible Java Card applets in the input jars</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. |
| |
| <a name="xlets"> </a> |
| <h3>All possible xlets in the input jars</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. |
| |
| <a name="androidapplications"> </a> |
| <h3>All possible Android applications in the input jars</h3> |
| These options shrink, optimize, and obfuscate all public activities, services, |
| broadcast receivers, and content providers in <code>in.jar</code>: |
| <pre> |
| -injars in.jar |
| -outjars out.jar |
| -libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar |
| -overloadaggressively |
| -repackageclasses '' |
| -allowaccessmodification |
| -optimizations !code/simplification/arithmetic |
| -printseeds |
| |
| -keep public class * extends android.app.Activity |
| -keep public class * extends android.app.Service |
| -keep public class * extends android.content.BroadcastReceiver |
| -keep public class * extends android.content.ContentProvider |
| </pre> |
| <p> |
| We're keeping all classes that extend the base classes that may be referenced |
| by the <code>AndroidManifest.xml</code> file of the application. |
| <p> |
| The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints |
| out which implementations 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>, and <a |
| href="#resourcefiles">resource files</a>. |
| |
| <a name="servlets"> </a> |
| <h3>All possible servlets in the input jars</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>. |
| |
| <a name="native"> </a> |
| <h3>Processing native methods</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 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. |
| <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. |
| |
| <a name="callback"> </a> |
| <h3>Processing callback methods</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. |
| |
| <a name="enumerations"> </a> |
| <h3>Processing enumeration classes</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 enum * { |
| public static **[] values(); |
| public static ** valueOf(java.lang.String); |
| } |
| </pre> |
| |
| <a name="serializable"> </a> |
| <h3>Processing serializable classes</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 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. |
| <p> |
| |
| <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; |
| 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>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://java.sun.com/javase/6/docs/platform/serialization/spec/class.html#4100">Stream |
| Unique Identifiers</a> of Sun's <a |
| href="http://java.sun.com/javase/6/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; |
| 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>". |
| |
| </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. |
| |
| <a name="beans"> </a> |
| <h3>Processing bean classes</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 should encompasses 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. |
| |
| <a name="annotations"> </a> |
| <h3>Processing annotations</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> |
| |
| <a name="database"> </a> |
| <h3>Processing database drivers</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). |
| |
| <a name="componentui"> </a> |
| <h3>Processing ComponentUI classes</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. |
| |
| <a name="rmi"> </a> |
| <h3>Processing RMI code</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. |
| |
| <a name="resourcefiles"> </a> |
| <h3>Processing resource files</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. |
| |
| <a name="stacktrace"> </a> |
| <h3>Producing useful obfuscated stack traces</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. |
| |
| <a name="repackaging"> </a> |
| <h3>Obfuscating package names</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. |
| |
| <a name="restructuring"> </a> |
| <h3>Restructuring the output archives</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. |
| |
| <a name="filtering"> </a> |
| <h3>Filtering the input and the output</h3> |
| |
| If you want even greater control, you can add filters 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 |
| the grouping of input and output. |
| |
| <a name="multiple"> </a> |
| <h3>Processing multiple applications at once</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 the processed application jars, with their original names. |
| |
| <a name="incremental"> </a> |
| <h3>Incremental obfuscation</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> |
| |
| <a name="microedition"> </a> |
| <h3>Preverifying class files for Java Micro Edition</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 compared to the traditional external |
| preverifier. |
| <pre> |
| -injars in.jar |
| -outjars out.jar |
| -libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar |
| -libraryjars /usr/local/java/wtk2.1/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. |
| |
| <a name="upgrade"> </a> |
| <h3>Upgrading class files to Java 6</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. |
| |
| <a name="deadcode"> </a> |
| <h3>Finding dead code</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> |
| |
| <a name="structure"> </a> |
| <h3>Printing out the internal structure of class files</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. |
| |
| <a name="annotated"> </a> |
| <h3>Using annotations to configure ProGuard</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. |
| <p> |
| |
| <hr> |
| <address> |
| Copyright © 2002-2009 |
| <a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>. |
| </address> |
| </body> |
| </html> |