You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1621 lines
60 KiB
1621 lines
60 KiB
<!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.saikoa.com/dexguard">DexGuard</a> <a class="largebutton" target="_top" href="http://www.saikoa.com/">Saikoa</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.saikoa.com/dexguard">DexGuard</a>
|
|
<a class="largebutton" target="_top" href="http://www.saikoa.com/">Saikoa</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 resource injection</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 resource injection</a></h3>
|
|
|
|
If your application is using JEE-style resource 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="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.
|
|
<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-2014
|
|
<a target="other" href="http://www.lafortune.eu/">Eric Lafortune</a> @ <a target="top" href="http://www.saikoa.com/">Saikoa</a>.
|
|
</address>
|
|
</body>
|
|
</html>
|