1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
|
<!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="#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="#servlets">All possible servlets in the input jars</a>
<li><a href="#library">Processing a library</a>
<li><a href="#native">Processing native methods</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="#rmi">Processing RMI code</a>
<li><a href="#stacktrace">Producing useful obfuscated stack traces</a>
<li><a href="#multiple">Processing multiple applications at once</a>
<li><a href="#incremental">Incremental obfuscation</a>
<li><a href="#deadcode">Finding dead code</a>
<li><a href="#structure">Printing out the internal structure of class files</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
-overloadaggressively
-defaultpackage ''
-allowaccessmodification
-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 the 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 using the <code>-overloadaggressively</code>,
<code>-defaultpackage</code>, and <code>-allowaccessmodification</code>
options to shave off some extra bytes, but we could leave them out as well.
The <code>-defaultpackage</code> directive moves all classes to the given
package, in this case the root package. Only <code>proguard.ProGuard</code>
keeps its original name.
<p>
We're writing out an obfuscation mapping file with <code>-printmapping</code>,
for de-obfuscating any stack traces later on, or for incremental obfuscation of
extensions.
<p>
In general, you might need a few additional directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</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 directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</a>.
<a name="midlet"> </a>
<h3>A typical midlet</h3>
These options shrink, optimize, and obfuscate the J2ME 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
-defaultpackage ''
-allowaccessmodification
-keep public class mypackage.MyMIDlet
</pre>
<p>
Note how we're now targeting the J2ME run-time environment of
<code>midpapi20.jar</code> and <code>cldcapi11.jar</code>, instead of the J2SE
run-time environment <code>rt.jar</code>. You can target other J2ME
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>
If applicable, you should add directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</a>.
<p>
You must preverify your midlets <i>after</i> having processed them, using
J2ME's <code>preverify</code> tool. Because this tool unpacks your processed
jars, you should use ProGuard's <code>-dontusemixedcaseclassnames</code>
option on platforms with case-insensitive filing systems, such as Windows.
<p>
Please note the in-depth article <a
href="http://developers.sun.com/techtopics/mobility/midp/ttips/proguard/">"Obfuscating
MIDlet Suites with ProGuard"</a> at <a
href="http://developers.sun.com/">developers.sun.com</a>.
<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 <code>-keepclasseswithmembers</code>. We don't want to preserve
all classes, just all classes that have main methods, and those methods.
<p>
The <code>-printseeds</code> 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 directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</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 <code>-printseeds</code> option prints out which applets exactly
will be preserved.
<p>
If applicable, you should add directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</a>.
<a name="midlets"> </a>
<h3>All possible midlets in the input jars</h3>
These options shrink, optimize, and obfuscate all public J2ME 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
-defaultpackage ''
-allowaccessmodification
-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>
And again, the <code>-printseeds</code> option prints out which midlets exactly
will be preserved.
<p>
If applicable, you should add directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</a>.
<p>
You must preverify your midlets <i>after</i> having processed them, using
J2ME's <code>preverify</code> tool. Because this tool unpacks your processed
jars, you should use ProGuard's <code>-dontusemixedcaseclassnames</code>
option on platforms with case-insensitive filing systems, such as Windows.
<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>
And again, the <code>-printseeds</code> option prints out which servlets
exactly will be preserved.
<p>
If applicable, you should add directives for processing <a
href="#native">native methods</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, or <a
href="#annotations">annotations</a>.
<a name="library"> </a>
<h3>Processing a 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 InnerClasses,SourceFile,LineNumberTable,Deprecated,
Signature,*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 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();
}
-keepclassmembers class * extends java.lang.Enum {
public **[] values();
}
</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
<code>-keep</code> directives.
<p>
The <code>-keepclassmembernames</code> directive 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>
We've added some directives for keeping the "Deprecated" attribute, for <a
href="#stacktrace">useful stack traces</a>, for <a href="#native">native
methods</a>, <a href="#serializable">serializable classes</a>, and for <a
href="#annotations">annotations</a> (possibly with enumerations), which are
all discussed in their respective examples.
<p>
The "InnerClasses" attribute (or more precisely, its source name part) has to
be preserved as well, 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.
<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 <code>-keepclasseswithmembernames</code>. 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 have your native code, so it can'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 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 directives:
<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 <code>-keepclassmembers</code> option makes sure that any
serialization methods are kept. By using this directive instead of the
basic <code>-keep</code> directive, 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 directives 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 !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> line makes sure that field is preserved.
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 chapter on <a
href="http://java.sun.com/j2se/1.4/docs/guide/serialization/spec/class.html#wp4100">Stream
Unique Identifiers</a> of Sun's <a
href="http://java.sun.com/j2se/1.4/docs/guide/serialization/">Object
Serialization Guide</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 !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 directives 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 directives 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 will
often produce more compact results.
<a name="beans"> </a>
<h3>Processing bean classes</h3>
If your application, applet, servlet, library, etc., uses extensive
introspection on bean classes to find bean editor classes, or getter and
setter methods, then configuration may become laborious. 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 encompasses a wide range
of setters and getters:
<pre>
-keep class mybeans.** {
void set*(%);
void set*(**);
void set*(%[]);
void set*(**[]);
void set*(int, %);
void set*(int, **);
% get*();
** get*();
%[] get*();
**[] get*();
% get*(int);
** get*(int);
}
</pre>
<p>
The '<code>%</code>' wildcard matches any primitive type, while the
'<code>**</code>' wildcard matches any class name. Array types have to be
specified explicitly. This results in a short list of alternative method
signatures.
<a name="annotations"> </a>
<h3>Processing annotations</h3>
As of JDK 5.0, class files can contain annotations. 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*
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
}
</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>
If your annotations contain enumeration classes, you'll have to preserve the
<code>values()</code> method in these classes. The run-time environment
accesses this method by introspection (Isn't that just grand? Introspection is
the self-modifying code of a new generation).
<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
will have to be preserved as well:
<pre>
-keepattributes EnclosingMethod
</pre>
<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>
-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 directive keeps all your Remote interfaces and their methods. The
second one keeps all the implementations, along with their particular RMI
constructors, if any.
<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="multiple"> </a>
<h3>Processing multiple applications at once</h3>
You can process several 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
-injars application.war
-outjars processed_applications
</pre>
<p>
After processing, the directory <code>processed_applications</code> will
contain the processed application jars and war, with their original names.
<p>
If you want explicit control over the output names, or 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 <code>-injars</code> and
<code>-outjars</code> options. For example:
<pre>
-injars application1.jar
-injars application2.jar
-injars application3.jar
-outjars application_out1.war
-injars application.war
-outjars application_out2.war
</pre>
<p>
This configuration creates two wars: one containing all processed application
jars, and one containing the processed contents of the input war.
<p>
Note that ProGuard will try to package output archives in a sensible way,
reconstructing the input entries as much as required. 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.
<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
-libraryjars <java.home>/lib/rt.jar
-libraryjars proguard.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: the new one as the input jar, and the old
one as a library jar. The <code>-applymapping</code> 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.
<a name="deadcode"> </a>
<h3>Finding dead code</h3>
These options list unused fields and methods in the application
<code>mypackage.MyApplication</code>:
<pre>
-injars in.jar
-libraryjars <java.home>/lib/rt.jar
-dontoptimize
-dontobfuscate
-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.
<p>
We're saving a little bit of time by skipping the optimization and obfuscation
steps.
<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
-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.
<p>
<hr>
<address>
Copyright © 2002-2005
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
</html>
|