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 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
|
<!doctype html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<meta http-equiv="content-style-type" content="text/css">
<link rel="stylesheet" type="text/css" href="style.css">
<title>ProGuard Examples</title>
</head>
<body>
<h2>Examples</h2>
Some typical useful configurations:
<ol>
<li><a href="#application">A typical application</a>
<li><a href="#applet">A typical applet</a>
<li><a href="#midlet">A typical midlet</a>
<li><a href="#jcapplet">A typical Java Card applet</a>
<li><a href="#xlet">A typical xlet</a>
<li><a href="#androidapplication">A typical Android application</a>
<li><a href="#library">A typical library</a>
<li><a href="#applications">All possible applications in the input jars</a>
<li><a href="#applets">All possible applets in the input jars</a>
<li><a href="#midlets">All possible midlets in the input jars</a>
<li><a href="#jcapplets">All possible Java Card applets in the input jars</a>
<li><a href="#xlets">All possible xlets in the input jars</a>
<li><a href="#androidapplications">All possible Android applications in the input jars</a>
<li><a href="#servlets">All possible servlets in the input jars</a>
<li><a href="#native">Processing native methods</a>
<li><a href="#callback">Processing callback methods</a>
<li><a href="#enumerations">Processing enumeration classes</a>
<li><a href="#serializable">Processing serializable classes</a>
<li><a href="#beans">Processing bean classes</a>
<li><a href="#annotations">Processing annotations</a>
<li><a href="#database">Processing database drivers</a>
<li><a href="#componentui">Processing ComponentUI classes</a>
<li><a href="#rmi">Processing RMI code</a>
<li><a href="#resourcefiles">Processing resource files</a>
<li><a href="#stacktrace">Producing useful obfuscated stack traces</a>
<li><a href="#repackaging">Obfuscating package names</a>
<li><a href="#restructuring">Restructuring the output archives</a>
<li><a href="#filtering">Filtering the input and the output</a>
<li><a href="#multiple">Processing multiple applications at once</a>
<li><a href="#incremental">Incremental obfuscation</a>
<li><a href="#microedition">Preverifying class files for Java Micro Edition</a>
<li><a href="#upgrade">Upgrading class files to Java 6</a>
<li><a href="#deadcode">Finding dead code</a>
<li><a href="#structure">Printing out the internal structure of class files</a>
<li><a href="#annotated">Using annotations to configure ProGuard</a>
</ol>
You can find some sample configuration files in the <code>examples</code>
directory of the ProGuard distribution.
<a name="application"> </a>
<h3>A typical application</h3>
To shrink, optimize, and obfuscate the ProGuard application itself, one would
typically create a configuration file <code>proguard.pro</code> and then type:
<pre>
java -jar proguard.jar @proguard.pro
</pre>
<p>
The configuration file would contain the following options:
<pre>
-injars proguard.jar
-outjars proguard_out.jar
-libraryjars <java.home>/lib/rt.jar
-printmapping proguard.map
-keep public class proguard.ProGuard {
public static void main(java.lang.String[]);
}
</pre>
<p>
Note the use of the <code><java.home></code> system property; it is
replaced automatically.
<p>
Also note that all type names are fully specified:
<code>proguard.ProGuard</code> and <code>java.lang.String[]</code>.
<p>
The access modifiers <code>public</code> and <code>static</code> are not
really required in this case, since we know a priori that the specified class
and method have the proper access flags. It just looks more familiar this way.
<p>
We're writing out an obfuscation mapping file with <a
href="usage.html#printmapping"><code>-printmapping</code></a>, for
de-obfuscating any stack traces later on, or for incremental obfuscation of
extensions.
<p>
We can further improve the results with a few additional options:
<pre>
-optimizationpasses 3
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
</pre>
These options are not required; they just shave off some extra bytes from the
output jar, by performing up to 3 optimization passes, and by aggressively
obfuscating class members and <a href="#repackaging">package names</a>.
<p>
In general, you might need a few additional options for processing <a
href="#native">native methods</a>, <a href="#callback">callback methods</a>,
<a href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>. For processing 'simple' applications like ProGuard, that is not
required.
<a name="applet"> </a>
<h3>A typical applet</h3>
These options shrink, optimize, and obfuscate the applet
<code>mypackage.MyApplet</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-keep public class mypackage.MyApplet
</pre>
<p>
The typical applet methods will be preserved automatically, since
<code>mypackage.MyApplet</code> is an extension of the <code>Applet</code>
class in the library <code>rt.jar</code>.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, <a
href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
<a name="midlet"> </a>
<h3>A typical midlet</h3>
These options shrink, optimize, obfuscate, and preverify the midlet
<code>mypackage.MyMIDlet</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
-libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-microedition
-keep public class mypackage.MyMIDlet
</pre>
<p>
Note how we're now targeting the Java Micro Edition run-time environment of
<code>midpapi20.jar</code> and <code>cldcapi11.jar</code>, instead of the Java
Standard Edition run-time environment <code>rt.jar</code>. You can target
other JME environments by picking the appropriate jars.
<p>
The typical midlet methods will be preserved automatically, since
<code>mypackage.MyMIDlet</code> is an extension of the <code>MIDlet</code>
class in the library <code>midpapi20.jar</code>.
<p>
The <a href="usage.html#microedition"><code>-microedition</code></a> option
makes sure the class files are preverified for Java Micro Edition, producing
compact <code>StackMap</code> attributes. It is no longer necessary to run an
external preverifier.
<p>
Be careful if you do use the external <code>preverify</code> tool on a platform
with a case-insensitive filing system, such as Windows. Because this tool
unpacks your processed jars, you should then use ProGuard's <a
href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
option.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a> and <a href="#resourcefiles">resource files</a>.
<p>
Note that you will still have to adapt the midlet jar size in the
corresponding jad file; ProGuard doesn't do that for you.
<a name="jcapplet"> </a>
<h3>A typical Java Card applet</h3>
These options shrink, optimize, and obfuscate the Java Card applet
<code>mypackage.MyApplet</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
-dontwarn java.lang.Class
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-keep public class mypackage.MyApplet
</pre>
<p>
The configuration is very similar to the configuration for midlets, except that
it now targets the Java Card run-time environment. This environment doesn't
have java.lang.Class, so we're telling ProGuard not to worry about it.
<a name="xlet"> </a>
<h3>A typical xlet</h3>
These options shrink, optimize, and obfuscate the xlet
<code>mypackage.MyXlet</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/jtv1.1/javatv.jar
-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-keep public class mypackage.MyXlet
</pre>
<p>
The configuration is very similar to the configuration for midlets, except that
it now targets the CDC run-time environment with the Java TV API.
<a name="androidapplication"> </a>
<h3>A typical Android application</h3>
These options shrink, optimize, and obfuscate the simple Android application
based on a single activity <code>mypackage.MyActivity</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keep public class mypackage.MyActivity
</pre>
<p>
The configuration is very similar to the configuration for midlets, except that
it now targets the Android run-time environment.
<p>
The <a href="usage.html#optimizations"><code>-optimizations</code></a> option
disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, and <a
href="#resourcefiles">resource files</a>.
<a name="library"> </a>
<h3>A typical library</h3>
These options shrink, optimize, and obfuscate an entire library, keeping all
public and protected classes and class members, native method names, and
serialization code:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keep public class * {
public protected *;
}
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
</pre>
<p>
This configuration should preserve everything we'll ever want to access in the
library. Only if there are any other non-public classes or methods that are
invoked dynamically, they should be specified using additional <a
href="usage.html#keep"><code>-keep</code></a> options.
<p>
The <a
href="usage.html#keepclassmembernames"><code>-keepclassmembernames</code></a>
option for the <code>class$</code> methods is not strictly necessary. These
methods are inserted by the <code>javac</code> compiler and the
<code>jikes</code> compiler respectively, to implement the <code>.class</code>
construct. ProGuard will automatically detect them and deal with them, even
when their names have been obfuscated. However, older versions of ProGuard and
other obfuscators may rely on the original method names. It may therefore be
helpful to preserve them, in case these other obfuscators are ever used for
further obfuscation of the library.
<p>
The "Exceptions" attribute has to be preserved, so the compiler knows which
exceptions methods may throw.
<p>
The "InnerClasses" attribute (or more precisely, its source name part) has to
be preserved too, for any inner classes that can be referenced from outside the
library. The <code>javac</code> compiler would be unable to find the inner
classes otherwise.
<p>
The "Signature" attribute is required to be able to access generic types when
compiling in JDK 5.0 and higher.
<p>
Finally, we're keeping the "Deprecated" attribute and the attributes for
producing <a href="#stacktrace">useful stack traces</a>.
<p>
We've also added some options for for processing <a href="#native">native
methods</a>, <a href="#enumerations">enumerations</a>, <a
href="#serializable">serializable classes</a>, and <a
href="#annotations">annotations</a>, which are all discussed in their
respective examples.
<a name="applications"> </a>
<h3>All possible applications in the input jars</h3>
These options shrink, optimize, and obfuscate all public applications in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-printseeds
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
</pre>
<p>
Note the use of <a
href="usage.html#keepclasseswithmembers"><code>-keepclasseswithmembers</code></a>.
We don't want to preserve all classes, just all classes that have main
methods, and those methods.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which classes exactly will be preserved, so we know for sure we're getting
what we want.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, <a
href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
<a name="applets"> </a>
<h3>All possible applets in the input jars</h3>
These options shrink, optimize, and obfuscate all public applets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-printseeds
-keep public class * extends java.applet.Applet
</pre>
<p>
We're simply keeping all classes that extend the <code>Applet</code> class.
<p>
Again, the <a href="usage.html#printseeds"><code>-printseeds</code></a> option
prints out which applets exactly will be preserved.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, <a
href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
<a name="midlets"> </a>
<h3>All possible midlets in the input jars</h3>
These options shrink, optimize, obfuscate, and preverify all public midlets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
-libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-microedition
-printseeds
-keep public class * extends javax.microedition.midlet.MIDlet
</pre>
<p>
We're simply keeping all classes that extend the <code>MIDlet</code> class.
<p>
The <a href="usage.html#microedition"><code>-microedition</code></a> option
makes sure the class files are preverified for Java Micro Edition, producing
compact <code>StackMap</code> attributes. It is no longer necessary to run an
external preverifier.
<p>
Be careful if you do use the external <code>preverify</code> tool on a platform
with a case-insensitive filing system, such as Windows. Because this tool
unpacks your processed jars, you should then use ProGuard's <a
href="usage.html#dontusemixedcaseclassnames"><code>-dontusemixedcaseclassnames</code></a>
option.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which midlets exactly will be preserved.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a> and <a href="#resourcefiles">resource files</a>.
<p>
Note that you will still have to adapt the midlet jar size in the
corresponding jad file; ProGuard doesn't do that for you.
<a name="jcapplets"> </a>
<h3>All possible Java Card applets in the input jars</h3>
These options shrink, optimize, and obfuscate all public Java Card applets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/javacard2.2.2/lib/api.jar
-dontwarn java.lang.Class
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-printseeds
-keep public class * implements javacard.framework.Applet
</pre>
<p>
We're simply keeping all classes that implement the <code>Applet</code>
interface.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which applets exactly will be preserved.
<a name="xlets"> </a>
<h3>All possible xlets in the input jars</h3>
These options shrink, optimize, and obfuscate all public xlets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/jtv1.1/javatv.jar
-libraryjars /usr/local/java/cdc1.1/lib/cdc.jar
-libraryjars /usr/local/java/cdc1.1/lib/btclasses.zip
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-printseeds
-keep public class * implements javax.tv.xlet.Xlet
</pre>
<p>
We're simply keeping all classes that implement the <code>Xlet</code> interface.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which xlets exactly will be preserved.
<a name="androidapplications"> </a>
<h3>All possible Android applications in the input jars</h3>
These options shrink, optimize, and obfuscate all public activities, services,
broadcast receivers, and content providers in <code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/android-1.5_r1/platforms/android-1.5/android.jar
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-printseeds
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
</pre>
<p>
We're keeping all classes that extend the base classes that may be referenced
by the <code>AndroidManifest.xml</code> file of the application.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which implementations exactly will be preserved.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, and <a
href="#resourcefiles">resource files</a>.
<a name="servlets"> </a>
<h3>All possible servlets in the input jars</h3>
These options shrink, optimize, and obfuscate all public servlets in
<code>in.jar</code>:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-libraryjars /usr/local/java/servlet/servlet.jar
-printseeds
-keep public class * implements javax.servlet.Servlet
</pre>
<p>
Keeping all servlets is very similar to keeping all applets. The servlet API
is not part of the standard run-time jar, so we're specifying it as a library.
Don't forget to use the right path name.
<p>
We're then keeping all classes that implement the <code>Servlet</code>
interface. We're using the <code>implements</code> keyword because it looks
more familiar in this context, but it is equivalent to <code>extends</code>,
as far as ProGuard is concerned.
<p>
The <a href="usage.html#printseeds"><code>-printseeds</code></a> option prints
out which servlets exactly will be preserved.
<p>
If applicable, you should add options for processing <a href="#native">native
methods</a>, <a href="#callback">callback methods</a>, <a
href="#enumerations">enumerations</a>, <a href="#serializable">serializable
classes</a>, <a href="#beans">bean classes</a>, <a
href="#annotations">annotations</a>, and <a href="#resourcefiles">resource
files</a>.
<a name="native"> </a>
<h3>Processing native methods</h3>
If your application, applet, servlet, library, etc., contains native methods,
you'll want to preserve their names and their classes' names, so they can
still be linked to the native library. The following additional option will
ensure that:
<pre>
-keepclasseswithmembernames class * {
native <methods>;
}
</pre>
<p>
Note the use of <a
href="usage.html#keepclasseswithmembernames"><code>-keepclasseswithmembernames</code></a>.
We don't want to preserve all classes or all native methods; we just want to
keep the relevant names from being obfuscated.
<p>
ProGuard doesn't look at your native code, so it won't automatically preserve
the classes or class members that are invoked by the native code. These are
entry points, which you'll have to specify explicitly. <a
href="callback">Callback methods</a> are discussed below as a typical example.
<a name="callback"> </a>
<h3>Processing callback methods</h3>
If your application, applet, servlet, library, etc., contains callback
methods, which are called from external code (native code, scripts,...),
you'll want to preserve them, and probably their classes too. They are just
entry points to your code, much like, say, the main method of an application.
If they aren't preserved by other <code>-keep</code> options, something like
the following option will keep the callback class and method:
<pre>
-keep class mypackage.MyCallbackClass {
void myCallbackMethod(java.lang.String);
}
</pre>
<p>
This will preserve the given class and method from being removed or renamed.
<a name="enumerations"> </a>
<h3>Processing enumeration classes</h3>
If your application, applet, servlet, library, etc., contains enumeration
classes, you'll have to preserve some special methods. Enumerations were
introduced in Java 5. The java compiler translates enumerations into classes
with a special structure. Notably, the classes contain implementations of some
static methods that the run-time environment accesses by introspection (Isn't
that just grand? Introspection is the self-modifying code of a new
generation). You have to specify these explicitly, to make sure they aren't
removed or obfuscated:
<pre>
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
</pre>
<a name="serializable"> </a>
<h3>Processing serializable classes</h3>
More complex applications, applets, servlets, libraries, etc., may contain
classes that are serialized. Depending on the way in which they are used, they
may require special attention:
<ul>
<li>Often, serialization is simply a means of transporting data, without
long-term storage. Classes that are shrunk and obfuscated should then
continue to function fine with the following additional options:
<pre>
-keepclassmembers class * implements java.io.Serializable {
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
</pre>
<p>
The <a
href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a>
option makes sure that any serialization methods are kept. By using this
option instead of the basic <code>-keep</code> option, we're not
forcing preservation of <i>all</i> serializable classes, just preservation
of the listed members of classes that are actually used.
<p>
<li>Sometimes, the serialized data are stored, and read back later into newer
versions of the serializable classes. One then has to take care the classes
remain compatible with their unprocessed versions and with future
processed versions. In such cases, the relevant classes will most likely
have <code>serialVersionUID</code> fields. The following options should
then be sufficient to ensure compatibility over time:
<pre>
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
</pre>
<p>
The <code>serialVersionUID</code> and <code>serialPersistentFields</code>
lines makes sure those fields are preserved, if they are present.
The <code><fields></code> line preserves all non-static,
non-transient fields, with their original names. The introspection of the
serialization process and the de-serialization process will then find
consistent names.
<li>Occasionally, the serialized data have to remain compatible, but the
classes involved lack <code>serialVersionUID</code> fields. I imagine the
original code will then be hard to maintain, since the serial version UID
is then computed from a list of features the serializable class. Changing
the class ever so slightly may change the computed serial version UID. The
list of features is specified in the section on <a
href="http://java.sun.com/javase/6/docs/platform/serialization/spec/class.html#4100">Stream
Unique Identifiers</a> of Sun's <a
href="http://java.sun.com/javase/6/docs/platform/serialization/spec/serialTOC.html">Java
Object Serialization Specification</a>. The following directives should at
least partially ensure compatibility with the original classes:
<pre>
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
</pre>
<p>
The new options force preservation of the elements involved in the UID
computation. In addition, the user will have to manually specify all
interfaces of the serializable classes (using something like "<code>-keep
interface MyInterface</code>"), since these names are also used when
computing the UID. A fast but sub-optimal alternative would be simply
keeping all interfaces with "<code>-keep interface *</code>".
</ul>
<p>
Note that the above options may preserve more classes and class members
than strictly necessary. For instance, a large number of classes may implement
the <code>Serialization</code> interface, yet only a small number may actually
ever be serialized. Knowing your application and tuning the configuration
often produces more compact results.
<a name="beans"> </a>
<h3>Processing bean classes</h3>
If your application, applet, servlet, library, etc., makes extensive use of
introspection on bean classes to find bean editor classes, or getter and
setter methods, then configuration may become painful. There's not much else
you can do than making sure the bean class names, or the getter and setter
names don't change. For instance:
<pre>
-keep public class mypackage.MyBean {
public void setMyProperty(int);
public int getMyProperty();
}
-keep public class mypackage.MyBeanEditor
</pre>
<p>
If there are too many elements to list explicitly, wildcards in class names
and method signatures might be helpful. This example should encompasses all
possible setters and getters in classes in the package <code>mybeans</code>:
<pre>
-keep class mybeans.** {
void set*(***);
void set*(int, ***);
boolean is*();
boolean is*(int);
*** get*();
*** get*(int);
}
</pre>
<p>
The '<code>***</code>' wildcard matches any type (primitive or non-primitive,
array or non-array). The methods with the '<code>int</code>' arguments matches
properties that are lists.
<a name="annotations"> </a>
<h3>Processing annotations</h3>
If your application, applet, servlet, library, etc., uses annotations, you may
want to preserve them in the processed output. Annotations are represented by
attributes that have no direct effect on the execution of the code. However,
their values can be retrieved through introspection, allowing developers to
adapt the execution behavior accordingly. By default, ProGuard treats
annotation attributes as optional, and removes them in the obfuscation step.
If they are required, you'll have to specify this explicitly:
<pre>
-keepattributes *Annotation*
</pre>
<p>
For brevity, we're specifying a wildcarded attribute name, which will match
<code>RuntimeVisibleAnnotations</code>,
<code>RuntimeInvisibleAnnotations</code>,
<code>RuntimeVisibleParameterAnnotations</code>,
<code>RuntimeInvisibleParameterAnnotations</code>, and
<code>AnnotationDefault</code>. Depending on the purpose of the processed
code, you could refine this selection, for instance not keeping the run-time
invisible annotations (which are only used at compile-time).
<p>
Some code may make further use of introspection to figure out the enclosing
methods of anonymous inner classes. In that case, the corresponding attribute
has to be preserved as well:
<pre>
-keepattributes EnclosingMethod
</pre>
<a name="database"> </a>
<h3>Processing database drivers</h3>
Database drivers are implementations of the <code>Driver</code> interface.
Since they are often created dynamically, you may want to preserve any
implementations that you are processing as entry points:
<pre>
-keep class * implements java.sql.Driver
</pre>
<p>
This option also gets rid of the note that ProGuard prints out about
<code>(java.sql.Driver)Class.forName</code> constructs, if you are
instantiating a driver in your code (without necessarily implementing any
drivers yourself).
<a name="componentui"> </a>
<h3>Processing ComponentUI classes</h3>
Swing UI look and feels are implemented as extensions of the
<code>ComponentUI</code> class. For some reason, these have to contain a
static method <code>createUI</code>, which the Swing API invokes using
introspection. You should therefore always preserve the method as an entry
point, for instance like this:
<pre>
-keep class * extends javax.swing.plaf.ComponentUI {
public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
}
</pre>
<p>
This option also keeps the classes themselves.
<a name="rmi"> </a>
<h3>Processing RMI code</h3>
Reportedly, the easiest way to handle RMI code is to process the code with
ProGuard first and then invoke the <code>rmic</code> tool. If that is not
possible, you may want to try something like this:
<pre>
-keepattributes Exceptions
-keep interface * extends java.rmi.Remote {
<methods>;
}
-keep class * implements java.rmi.Remote {
<init>(java.rmi.activation.ActivationID, java.rmi.MarshalledObject);
}
</pre>
<p>
The first <code>-keep</code> option keeps all your Remote interfaces and their
methods. The second one keeps all the implementations, along with their
particular RMI constructors, if any.
<p>
The <code>Exceptions</code> attribute has to be kept too, because the RMI
handling code performs introspection to check whether the method signatures
are compatible.
<a name="resourcefiles"> </a>
<h3>Processing resource files</h3>
If your application, applet, servlet, library, etc., contains resource files,
it may be necessary to adapt their names and/or their contents when the
application is obfuscated. The following two options can achieve this
automatically:
<pre>
-adaptresourcefilenames **.properties,**.gif,**.jpg
-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
</pre>
<p>
The <a href="usage.html#adaptresourcefilenames">-adaptresourcefilenames</a>
option in this case renames properties files and image files in the processed
output, based on the obfuscated names of their corresponding class files (if
any). The <a
href="usage.html#adaptresourcefilecontents">-adaptresourcefilecontents</a>
option looks for class names in properties files and in the manifest file, and
replaces these names by the obfuscated names (if any). You'll probably want to
adapt the filters to suit your application.
<a name="stacktrace"> </a>
<h3>Producing useful obfuscated stack traces</h3>
These options let obfuscated applications or libraries produce stack traces
that can still be deciphered later on:
<pre>
-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
</pre>
<p>
We're keeping all source file attributes, but we're replacing their values by
the string "SourceFile". We could use any string. This string is already
present in all class files, so it doesn't take up any extra space. If you're
working with J++, you'll want to keep the "SourceDir" attribute as well.
<p>
We're also keeping the line number tables of all methods.
<p>
Whenever both of these attributes are present, the Java run-time environment
will include line number information when printing out exception stack traces.
<p>
The information will only be useful if we can map the obfuscated names back to
their original names, so we're saving the mapping to a file
<code>out.map</code>. The information can then be used by the <a
href="retrace/index.html">ReTrace</a> tool to restore the original stack trace.
<a name="repackaging"> </a>
<h3>Obfuscating package names</h3>
Package names can be obfuscated in various ways, with increasing levels of
obfuscation and compactness. For example, consider the following classes:
<pre>
mycompany.myapplication.MyMain
mycompany.myapplication.Foo
mycompany.myapplication.Bar
mycompany.myapplication.extra.FirstExtra
mycompany.myapplication.extra.SecondExtra
mycompany.util.FirstUtil
mycompany.util.SecondUtil
</pre>
<p>
Let's assume the class name <code>mycompany.myapplication.MyMain</code> is the
main application class that is kept by the configuration. All other class names
can be obfuscated.
<p>
By default, packages that contain classes that can't be renamed aren't renamed
either, and the package hierarchy is preserved. This results in obfuscated
class names like these:
<pre>
mycompany.myapplication.MyMain
mycompany.myapplication.a
mycompany.myapplication.b
mycompany.myapplication.a.a
mycompany.myapplication.a.b
mycompany.a.a
mycompany.a.b
</pre>
<p>
The <a
href="usage.html#flattenpackagehierarchy"><code>-flattenpackagehierarchy</code></a>
option obfuscates the package names further, by flattening the package
hierarchy of obfuscated packages:
<pre>
-flattenpackagehierarchy 'myobfuscated'
</pre>
<p>
The obfuscated class names then look as follows:
<pre>
mycompany.myapplication.MyMain
mycompany.myapplication.a
mycompany.myapplication.b
myobfuscated.a.a
myobfuscated.a.b
myobfuscated.b.a
myobfuscated.b.b
</pre>
<p>
Alternatively, the <a
href="usage.html#repackageclasses"><code>-repackageclasses</code></a> option
obfuscates the entire packaging, by combining obfuscated classes into a single
package:
<pre>
-repackageclasses 'myobfuscated'
</pre>
The obfuscated class names then look as follows:
<pre>
mycompany.myapplication.MyMain
mycompany.myapplication.a
mycompany.myapplication.b
myobfuscated.a
myobfuscated.b
myobfuscated.c
myobfuscated.d
</pre>
<p>
Additionally specifying the <a
href="usage.html#allowaccessmodification"><code>-allowaccessmodification</code></a>
option allows access permissions of classes and class members to
be broadened, opening up the opportunity to repackage all obfuscated classes:
<pre>
-repackageclasses 'myobfuscated'
-allowaccessmodification
</pre>
The obfuscated class names then look as follows:
<pre>
mycompany.myapplication.MyMain
myobfuscated.a
myobfuscated.b
myobfuscated.c
myobfuscated.d
myobfuscated.e
myobfuscated.f
</pre>
<p>
The specified target package can always be the root package. For instance:
<pre>
-repackageclasses ''
-allowaccessmodification
</pre>
The obfuscated class names are then the shortest possible names:
<pre>
mycompany.myapplication.MyMain
a
b
c
d
e
f
</pre>
<p>
Note that not all levels of obfuscation of package names may be acceptable for
all code. Notably, you may have to take into account that your application may
contain <a href="#resourcefiles">resource files</a> that have to be adapted.
<a name="restructuring"> </a>
<h3>Restructuring the output archives</h3>
In simple applications, all output classes and resources files are merged into
a single jar. For example:
<pre>
-injars classes
-injars in1.jar
-injars in2.jar
-injars in3.jar
-outjars out.jar
</pre>
<p>
This configuration merges the processed versions of the files in the
<code>classes</code> directory and the three jars into a single output jar
<code>out.jar</code>.
<p>
If you want to preserve the structure of your input jars (and/or wars, ears,
zips, or directories), you can specify an output directory (or a war, an ear,
or a zip). For example:
<pre>
-injars in1.jar
-injars in2.jar
-injars in3.jar
-outjars out
</pre>
<p>
The input jars will then be reconstructed in the directory <code>out</code>,
with their original names.
<p>
You can also combine archives into higher level archives. For example:
<pre>
-injars in1.jar
-injars in2.jar
-injars in3.jar
-outjars out.war
</pre>
<p>
The other way around, you can flatten the archives inside higher level
archives into simple archives:
<pre>
-injars in.war
-outjars out.jar
</pre>
<p>
This configuration puts the processed contents of all jars inside
<code>in.war</code> (plus any other contents of <code>in.war</code>) into
<code>out.jar</code>.
<p>
If you want to combine input jars (and/or wars, ears, zips, or directories)
into output jars (and/or wars, ears, zips, or directories), you can group the
<a href="usage.html#injars"><code>-injars</code></a> and <a
href="usage.html#outjars"><code>-outjars</code></a> options. For example:
<pre>
-injars base_in1.jar
-injars base_in2.jar
-injars base_in3.jar
-outjars base_out.jar
-injars extra_in.jar
-outjars extra_out.jar
</pre>
<p>
This configuration puts the processed results of all <code>base_in*.jar</code>
jars into <code>base_out.jar</code>, and the processed results of the
<code>extra_in.jar</code> into <code>extra_out.jar</code>. Note that only the
order of the options matters; the additional whitespace is just for clarity.
<p>
This grouping, archiving, and flattening can be arbitrarily complex. ProGuard
always tries to package output archives in a sensible way, reconstructing the
input entries as much as required.
<a name="filtering"> </a>
<h3>Filtering the input and the output</h3>
If you want even greater control, you can add filters to the input and the
output, filtering out zips, ears, wars, jars, and/or ordinary files. For
example, if you want to disregard certain files from an input jar:
<pre>
-injars in.jar(!images/**)
-outjars out.jar
</pre>
<p>
This configuration removes any files in the <code>images</code> directory and
its subdirectories.
<p>
Such filters can be convenient for avoiding warnings about duplicate files in
the output. For example, only keeping the manifest file from a first input jar:
<pre>
-injars in1.jar
-injars in2.jar(!META-INF/MANIFEST.MF)
-injars in3.jar(!META-INF/MANIFEST.MF)
-outjars out.jar
</pre>
<p>
Another useful application is speeding up the processing by ProGuard, by
disregarding a large number of irrelevant classes in the runtime library jar:
<pre>
-libraryjars <java.home>/lib/rt.jar(java/**,javax/**)
</pre>
<p>
The filter makes ProGuard disregard <code>com.sun.**</code> classes, for
instance , which don't affect the processing of ordinary applications.
<p>
It is also possible to filter the jars (and/or wars, ears, zips) themselves,
based on their names. For example:
<pre>
-injars in(**/acme_*.jar;)
-outjars out.jar
</pre>
<p>
Note the semi-colon in the filter; the filter in front of it applies to jar
names. In this case, only <code>acme_*.jar</code> jars are read from the
directory <code>in</code> and its subdirectories. Filters for war names, ear
names, and zip names can be prefixed with additional semi-colons. All types of
filters can be combined. They are orthogonal.
<p>
On the other hand, you can also filter the output, in order to control what
content goes where. For example:
<pre>
-injars in.jar
-outjars code_out.jar(**.class)
-outjars resources_out.jar
</pre>
<p>
This configuration splits the processed output, sending <code>**.class</code>
files to <code>code_out.jar</code>, and all remaining files to
<code>resources_out.jar</code>.
<p>
Again, the filtering can be arbitrarily complex, especially when combined with
the grouping of input and output.
<a name="multiple"> </a>
<h3>Processing multiple applications at once</h3>
You can process several dependent or independent applications (or applets,
midlets,...) in one go, in order to save time and effort. ProGuard's input and
output handling offers various ways to keep the output nicely structured.
<p>
The easiest way is to specify your input jars (and/or wars, ears, zips, and
directories) and a single output directory. ProGuard will then reconstruct the
input in this directory, using the original jar names. For example, showing
just the input and output options:
<pre>
-injars application1.jar
-injars application2.jar
-injars application3.jar
-outjars processed_applications
</pre>
<p>
After processing, the directory <code>processed_applications</code> will
contain the processed application jars, with their original names.
<a name="incremental"> </a>
<h3>Incremental obfuscation</h3>
After having <a href="#application">processed an application</a>, e.g.
ProGuard itself, you can still incrementally add other pieces of code that
depend on it, e.g. the ProGuard GUI:
<pre>
-injars proguardgui.jar
-outjars proguardgui_out.jar
-injars proguard.jar
-outjars proguard_out.jar
-libraryjars <java.home>/lib/rt.jar
-applymapping proguard.map
-keep public class proguard.gui.ProGuardGUI {
public static void main(java.lang.String[]);
}
</pre>
<p>
We're reading both unprocessed jars as input. Their processed contents will go
to the respective output jars. The <a
href="usage.html#applymapping"><code>-applymapping</code></a> option then
makes sure the ProGuard part of the code gets the previously produced
obfuscation mapping. The final application will consist of the obfuscated
ProGuard jar and the additional obfuscated GUI jar.
<p>
The added code in this example is straightforward; it doesn't affect the
original code. The <code>proguard_out.jar</code> will be identical to the one
produced in the initial processing step. If you foresee adding more complex
extensions to your code, you should specify the options <a
href="usage.html#useuniqueclassmembernames"><code>-useuniqueclassmembernames</code></a>,
<a href="usage.html#dontshrink"><code>-dontshrink</code></a>, and <a
href="usage.html#dontoptimize"><code>-dontoptimize</code></a> <i>in the
original processing step</i>. These options ensure that the obfuscated base
jar will always remain usable without changes. You can then specify the base
jar as a library jar:
<pre>
-injars proguardgui.jar
-outjars proguardgui_out.jar
-libraryjars proguard.jar
-libraryjars <java.home>/lib/rt.jar
-applymapping proguard.map
-keep public class proguard.gui.ProGuardGUI {
public static void main(java.lang.String[]);
}
</pre>
<a name="microedition"> </a>
<h3>Preverifying class files for Java Micro Edition</h3>
Even if you're not interested in shrinking, optimizing, and obfuscating your
midlets, as shown in the <a href="#midlets">midlets example</a>, you can still
use ProGuard to preverify the class files for Java Micro Edition. ProGuard
produces slightly more compact results compared to the traditional external
preverifier.
<pre>
-injars in.jar
-outjars out.jar
-libraryjars /usr/local/java/wtk2.1/lib/midpapi20.jar
-libraryjars /usr/local/java/wtk2.1/lib/cldcapi11.jar
-dontshrink
-dontoptimize
-dontobfuscate
-microedition
</pre>
<p>
We're not processing the input, just making sure the class files are
preverified by targeting them at Java Micro Edition with the <a
href="usage.html#microedition"><code>-microedition</code></a> option. Note
that we don't need any <code>-keep</code> options to specify entry points; all
class files are simply preverified.
<a name="upgrade"> </a>
<h3>Upgrading class files to Java 6</h3>
The following options upgrade class files to Java 6, by updating their
internal version numbers and preverifying them. The class files can then be
loaded more efficiently by the Java 6 Virtual Machine.
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-dontshrink
-dontoptimize
-dontobfuscate
-target 1.6
</pre>
<p>
We're not processing the input, just retargeting the class files with the <a
href="usage.html#target"><code>-target</code></a> option. They will
automatically be preverified for Java 6 as a result. Note that we don't need
any <code>-keep</code> options to specify entry points; all class files are
simply updated and preverified.
<a name="deadcode"> </a>
<h3>Finding dead code</h3>
These options list unused classes, fields, and methods in the application
<code>mypackage.MyApplication</code>:
<pre>
-injars in.jar
-libraryjars <java.home>/lib/rt.jar
-dontoptimize
-dontobfuscate
-dontpreverify
-printusage
-keep public class mypackage.MyApplication {
public static void main(java.lang.String[]);
}
</pre>
<p>
We're not specifying an output jar, just printing out some results. We're
saving some processing time by skipping the other processing steps.
<p>
The java compiler inlines primitive constants and String constants
(<code>static final</code> fields). ProGuard would therefore list such fields
as not being used in the class files that it analyzes, even if they <i>are</i>
used in the source files. We can add a <a
href="usage.html#keepclassmembers"><code>-keepclassmembers</code></a> option
that keeps those fields a priori, in order to avoid having them listed:
<pre>
-keepclassmembers class * {
static final % *;
static final java.lang.String *;
}
</pre>
<a name="structure"> </a>
<h3>Printing out the internal structure of class files</h3>
These options print out the internal structure of all class files in the input
jar:
<pre>
-injars in.jar
-dontshrink
-dontoptimize
-dontobfuscate
-dontpreverify
-dump
</pre>
<p>
Note how we don't need to specify the Java run-time jar, because we're not
processing the input jar at all.
<a name="annotated"> </a>
<h3>Using annotations to configure ProGuard</h3>
The traditional ProGuard configuration allows to keep a clean separation
between the code and the configuration for shrinking, optimization, and
obfuscation. However, it is also possible to define specific annotations,
and then annotate the code to configure the processing.
<p>
You can find a set of such predefined annotations in the directory
<code>examples/annotations/lib</code> in the ProGuard distribution.
The annotation classes are defined in <code>annotations.jar</code>. The
corresponding ProGuard configuration (or meta-configuration, if you prefer)
is specified in <code>annotations.pro</code>. With these files, you can start
annotating your code. For instance, a java source file
<code>Application.java</code> can be annotated as follows:
<pre>
@KeepApplication
public class Application {
....
}
</pre>
<p>
The ProGuard configuration file for the application can then be simplified by
leveraging off these annotations:
<pre>
-injars in.jar
-outjars out.jar
-libraryjars <java.home>/lib/rt.jar
-include lib/annotations.pro
</pre>
<p>
The annotations are effectively replacing the application-dependent
<code>-keep</code> options. You may still wish to add traditional
<code>-keep</code> options for processing <a href="#native">native
methods</a>, <a href="#enumerations">enumerations</a>, <a
href="#serializable">serializable classes</a>, and <a
href="#annotations">annotations</a>.
<p>
The directory <code>examples/annotations</code> contains more examples that
illustrate some of the possibilities.
<p>
<hr>
<address>
Copyright © 2002-2009
<a href="http://www.graphics.cornell.edu/~eric/">Eric Lafortune</a>.
</address>
</body>
</html>
|