From 0dbfaec4213ece546e91cdfb3cb882ba0c147c47 Mon Sep 17 00:00:00 2001
From: ProGuard
+Some notable optimizations that aren't supported yet:
+
+ProGuard also comes with an obfuscator plug-in for the JME Wireless
+Toolkit.
+
+
+With variable string arguments, it's generally not possible to determine their
+possible values. They might be read from a configuration file, for instance.
+However, ProGuard will note a number of constructs like
+"
+
+
+
+
+
+
+Version 2, June 1991
+
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+
+0.
+ This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+
+
+1.
+ You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+
+2.
+ You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+
+
+
+
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+
+
+3.
+ You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+
+
+
+
+
+
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+4.
+ You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+
+
+5.
+ You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+
+
+6.
+ Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+
+
+7.
+ If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+
+8.
+ If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+
+
+9.
+ The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+
+
+
+10.
+ If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+
+
+ NO WARRANTY
+
+11.
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+
+
+12.
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+
+
+
+
+Copyright © 2002-2013 Eric Lafortune
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+In addition, as a special exception, Eric Lafortune gives permission to link
+the code of this program with the following stand-alone applications:
+Frequently Asked Questions
+
+Contents
+
+
+
+
+Class.forName
+ calls?What is shrinking?
+
+Java source code (.java files) is typically compiled to bytecode (.class
+files). Bytecode is more compact than Java source code, but it may still
+contain a lot of unused code, especially if it includes program libraries.
+Shrinking programs such as ProGuard can analyze bytecode and remove
+unused classes, fields, and methods. The program remains functionally
+equivalent, including the information given in exception stack traces.
+
+What is obfuscation?
+
+By default, compiled bytecode still contains a lot of debugging information:
+source file names, line numbers, field names, method names, argument names,
+variable names, etc. This information makes it straightforward to decompile
+the bytecode and reverse-engineer entire programs. Sometimes, this is not
+desirable. Obfuscators such as ProGuard can remove the debugging
+information and replace all names by meaningless character sequences, making
+it much harder to reverse-engineer the code. It further compacts the code as a
+bonus. The program remains functionally equivalent, except for the class
+names, method names, and line numbers given in exception stack traces.
+
+What is preverification?
+
+When loading class files, the class loader performs some sophisticated
+verification of the byte code. This analysis makes sure the code can't
+accidentally or intentionally break out of the sandbox of the virtual machine.
+Java Micro Edition and Java 6 introduced split verification. This means that
+the JME preverifier and the Java 6 compiler add preverification information to
+the class files (StackMap and StackMapTable attributes, respectively), in order
+to simplify the actual verification step for the class loader. Class files can
+then be loaded faster and in a more memory-efficient way. ProGuard can
+perform the preverification step too, for instance allowing to retarget older
+class files at Java 6.
+
+What kind of optimizations does ProGuard support?
+
+Apart from removing unused classes, fields, and methods in the shrinking step,
+ProGuard can also perform optimizations at the bytecode level, inside
+and across methods. Thanks to techniques like control flow analysis, data flow
+analysis, partial evaluation, static single assignment, global value numbering,
+and liveness analysis, ProGuard can:
+
+
+
+The positive effects of these optimizations will depend on your code and on
+the virtual machine on which the code is executed. Simple virtual machines may
+benefit more than advanced virtual machines with sophisticated JIT compilers.
+At the very least, your bytecode may become a bit smaller.
+
+
+
+Can I use ProGuard to process my commercial application?
+
+Yes, you can. ProGuard itself is distributed under the GPL, but this
+doesn't affect the programs that you process. Your code remains yours, and
+its license can remain the same.
+
+Does ProGuard work with Java 2? Java 5? Java 6? Java 7?
+
+Yes, ProGuard supports all JDKs from 1.1 up to and including 7.0. Java 2
+introduced some small differences in the class file format. Java 5 added
+attributes for generics and for annotations. Java 6 introduced optional
+preverification attributes. Java 7 made preverification obligatory and
+introduced support for dynamic languages. ProGuard handles all versions
+correctly.
+
+Does ProGuard work with Java Micro Edition?
+
+Yes. ProGuard itself runs in Java Standard Edition, but you can freely
+specify the run-time environment at which your programs are targeted,
+including Java Micro Edition. ProGuard then also performs the required
+preverification, producing more compact results than the traditional external
+preverifier.
+Does ProGuard work for Google Android code?
+
+Yes. Google's dx
compiler converts ordinary jar files into files
+that run on Android devices. By preprocessing the original jar files,
+ProGuard can significantly reduce the file sizes and boost the run-time
+performance of the code. It is distributed as part of the Android SDK.
+DexGuard,
+ProGuard's closed-source sibling for Android, offers additional
+optimizations and more application protection.
+
+Does ProGuard work for Blackberry code?
+
+It should. RIM's proprietary rapc
compiler converts ordinary JME
+jar files into cod files that run on Blackberry devices. The compiler performs
+quite a few optimizations, but preprocessing the jar files with
+ProGuard can generally still reduce the final code size by a few
+percent. However, the rapc
compiler also seems to contain some
+bugs. It sometimes fails on obfuscated code that is valid and accepted by other
+JME tools and VMs. Your mileage may therefore vary.
+
+Does ProGuard have support for Ant?
+
+Yes. ProGuard provides an Ant task, so that it integrates seamlessly
+into your Ant build process. You can still use configurations in
+ProGuard's own readable format. Alternatively, if you prefer XML, you
+can specify the equivalent XML configuration.
+
+Does ProGuard have support for Gradle?
+
+Yes. ProGuard also provides a Gradle task, so that it integrates into
+your Gradle build process. You can specify configurations in
+ProGuard's own format or embedded in the Groovy configuration.
+
+Does ProGuard have support for Maven?
+
+ProGuard's jar files are also distributed as artefacts from the Maven Central repository. There are some third-party
+plugins, like the android-maven-plugin that support ProGuard.
+DexGuard
+also has a compatible Maven plugin.
+
+Does ProGuard come with a GUI?
+
+Yes. First of all, ProGuard is perfectly usable as a command-line tool
+that can easily be integrated into any automatic build process. For casual
+users, there's also a graphical user interface that simplifies creating,
+loading, editing, executing, and saving ProGuard configurations.
+
+Does ProGuard handle
+
+Yes. ProGuard automatically handles constructs like
+Class.forName
calls?Class.forName("SomeClass")
and SomeClass.class
. The
+referenced classes are preserved in the shrinking phase, and the string
+arguments are properly replaced in the obfuscation phase.
+(SomeClass)Class.forName(variable).newInstance()
". These might
+be an indication that the class or interface SomeClass
and/or its
+implementations may need to be preserved. The developer can adapt his
+configuration accordingly.
+
+Does ProGuard handle resource files?
+
+Yes. ProGuard copies all non-class resource files, optionally adapting
+their names and their contents to the obfuscation that has been applied.
+
+Does ProGuard encrypt string constants?
+
+No. String encryption in program code has to be perfectly reversible by
+definition, so it only improves the obfuscation level. It increases the
+footprint of the code. However, by popular demand, ProGuard's
+closed-source sibling for Android, DexGuard, does provide string encryption, along with
+more protection techniques against static and dynamic analysis.
+
+Does ProGuard perform flow obfuscation?
+
+Not explicitly. Control flow obfuscation injects additional branches into the
+bytecode, in an attempt to fool decompilers. ProGuard does not do this,
+in order to avoid any negative effects on performance and size. However, the
+optimization step often already restructures the code to the point where most
+decompilers get confused.
+
+Does ProGuard support incremental obfuscation?
+
+Yes. This feature allows you to specify a previous obfuscation mapping file in
+a new obfuscation step, in order to produce add-ons or patches for obfuscated
+code.
+
+Can ProGuard obfuscate using reserved keywords?
+
+Yes. You can specify your own obfuscation dictionary, such as a list of
+reserved key words, identifiers with foreign characters, random source files,
+or a text by Shakespeare. Note that this hardly improves the obfuscation.
+Decent decompilers can automatically replace reserved keywords, and the effect
+can be undone fairly easily, by obfuscating again with simpler names.
+
+Can ProGuard reconstruct obfuscated stack traces?
+
+Yes. ProGuard comes with a companion tool, ReTrace, that can
+'de-obfuscate' stack traces produced by obfuscated applications. The
+reconstruction is based on the mapping file that ProGuard can write
+out. If line numbers have been obfuscated away, a list of alternative method
+names is presented for each obfuscated method name that has an ambiguous
+reverse mapping. Please refer to the ProGuard User
+Manual for more details.
+
+
+
+
+Copyright © 2002-2013
+Eric Lafortune.
+
+
+
diff --git a/docs/GPL.html b/docs/GPL.html
new file mode 100644
index 000000000..c7a24580c
--- /dev/null
+++ b/docs/GPL.html
@@ -0,0 +1,406 @@
+
+
+
+GNU General Public License
+Table of Contents
+
+
+
+
+
+
+GNU GENERAL PUBLIC LICENSE
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+
+
+
+Preamble
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+
+
+
+
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+
+
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+END OF TERMS AND CONDITIONS
+
+
diff --git a/docs/GPL_exception.html b/docs/GPL_exception.html
new file mode 100644
index 000000000..d610af891
--- /dev/null
+++ b/docs/GPL_exception.html
@@ -0,0 +1,57 @@
+
+
+
+Special Exception to the GNU General Public License
+
+
+
+and distribute linked combinations including the two. You must obey the GNU
+General Public License in all respects for all of the code used other than
+these programs. If you modify this file, you may extend this exception to your
+version of the file, but you are not obligated to do so. If you do not wish to
+do so, delete this exception statement from your version.
+
+ +Dirk Schnelle has contributed and maintained the first versions of the Ant +task. I have rewritten the implementation for version 3.0, but the XML schema +is still based on his work. +
+ +Marcel Patzlaff has initiated a series of artifacts in the Maven Central +repository. I am now maintaining them as part of the official builds. +
+ +Many other people have expressed their enthusiasm and have chimed in with +interesting ideas, bug reports, and bug fixes: Thorsten Heit, Oliver Retzl, +Jonathan Knudsen, Tarcisio Camara, Bob Drury, Dave Jarvis, Marc Chapman, Dave +Morehouse, Richard Osbaldeston, Peter Hawkins, Mark Sherington, David Sitsky, +James Manning, Ptolemy Oberin, Frank-Michael Moser, QZ Shines, Thomas Singer, +Michele Puccini, Roman Bednarek, Natalia Pujol, Daniel Sjöblom, Jan +Filipsky, Charles Smith, Gerrit Telkamp, Noel Grandin, Torbjörn +Söderstedt, Clemens Eisserer, Clark Bassett, Eduard Welch, Dawid Weiss, +Andrew Wilson, Sean Owen, Niels Gron, Ishan Mehta, Steven Adams, Xavier Kral, +Stefan Martin, Toby Reyelts, Bernhard Eder, Manfred Moser, Marco Blümel, +David Reiss, +and many more. Thanks! Your feedback has been invaluable. +
+ +Saikoa is providing the +financial resources for this project. At Saikoa, we're also developing +ProGuard's sibling for Android, +DexGuard. +
+ +SourceForge is providing the resources for hosting this +project and many other projects. +
+ +Sonatype and +the Maven Central repository are hosting the Maven artifacts. +
+ +The code and these web pages were written using Oracle/Sun's JDKs, Linux, +IntelliJ IDEA, GNU emacs, bash, sed, awk, and a whole host of other tools that +continue to make programming interesting. +
+ +And finally, I'm a great fan of Sanaware's Java Docking Library. + +
+This is a list of the programs of which I'm aware. Obviously, I've never +personally tested all of them. Many programs, even commercial ones, have been +abandoned. Please drop me a note if you know of any other shrinkers, +optimizers, obfuscators, or preverifiers, or if some information provided +below is incorrect. +
+ +
Author/Company | +Program | +Shrink. | +Optim. | +Obfusc. | +Preverif. | +License | +
---|---|---|---|---|---|---|
Eric Lafortune | +ProGuard | ++ | + | + | + | Free (GPL) | +
Jochen Hoenicke | +Jode | ++ | + | + | Free (GPL) | +|
Nate Nystrom | +Bloat | ++ | + | Free | +||
Hidetoshi Ohuchi | +Jarg | ++ | + | Free (BSD) | +||
yWorks | +yGuard | ++ | + | Free (no source) | +||
Mojo | +Minijar | ++ | Free (Apache) | +|||
RiggsHill Software | +GenJar | ++ | Free (Apache) | +|||
Apache | +Ant Classfileset | ++ | Free (Apache) | +|||
Carsten Elton Sørensen | +Treeshaker | ++ | Free (Apache) | +|||
Jörg Spieler | +UCDetector | ++ | Free (EPL) | +|||
Romain Guy | +Harvester | ++ | Free (BSD) | +|||
Emeric Vernat | +DCD | ++ | Free (LGPL) | +|||
Cristiano Sadun | +Pack | ++ | Free (LGPL) | +|||
Sable | +Soot | ++ | Free (LGPL) | +|||
Konstantin Knizhnik | +JavaGO | ++ | Free | +|||
Sable | +JBCO | ++ | Free (LGPL) | +|||
Jeffrey Wheaton | +ClassEncrypt | ++ | Free (GPL) | +|||
Thorsten Heit | +JavaGuard | ++ | Free (LGPL) | +|||
Patrick Mueller | +Mwobfu | ++ | Free (GPL) | +|||
BebboSoft | +Bb_mug | ++ | Free (no source) | +|||
Vít Šesták | +Preverifier | ++ | Free (EPL) | +|||
Saikoa | +DexGuard | ++ | + | + | Commercial | +|
PreEmptive | +DashOPro | ++ | + | + | Commercial | +|
Zelix | +KlassMaster | ++ | + | + | Commercial | +|
Sophia Cradle | +SophiaCompress | ++ | + | + | Commercial | +|
Eastridge Technology | +Jshrink | ++ | + | Commercial | +||
LeeSoftware | +Smokescreen Obfuscator | ++ | + | Commercial | +||
Innaworks | +mBooster | ++ | + | + | Commercial | +|
Sergey Sverdlov | +J.Class Optimizer | ++ | + | Commercial | +||
Smardec | +Allatori | ++ | + | Commercial | +||
U. of Arizona | +SandMark | ++ | + | Commercial | +||
Zenofx | +ClassGuard | ++ | Commercial | +|||
BIS Guard & Co. | +Java Antidecompiler | ++ | Commercial | +|||
Force 5 | +JCloak | ++ | Commercial | +|||
Semantic Designs | +Obfuscator | ++ | Commercial | +|||
Duckware | +Jobfuscate | ++ | Commercial | +|||
Arxan | +GuardIT | ++ | Commercial | +|||
Vasile Calmatui | +VasObfuLite | ++ | Free | +|||
IBM AlphaWorks | +JAX | ++ | + | + | (discontinued) | +|
NQ4 | +Joga | ++ | + | + | (discontinued?) | +|
Markus Jansen | +Jopt | ++ | + | + | (disappeared?) | +|
Alexander Shvets | +CafeBabe | ++ | + | (disappeared?) | +||
Brian Alliet | +Gcclass | ++ | (disappeared?) | +|||
Christian Grothoff | +Jamit | ++ | (disappeared?) | +|||
Haruaki Tamada | +DonQuixote | ++ | + | (disappeared?) | +||
Bajie | +JCMP | ++ | + | (disappeared?) | +||
Elegant Software | +JMangle | ++ | (disappeared?) | +|||
Eron Jokipii | +Jobe | ++ | (disappeared?) | +|||
JRC | +DeCaf | ++ | (disappeared?) | +|||
Dr. Java | +Marvin Obfuscator | ++ | (disappeared?) | +|||
IBM | +WSDD | ++ | + | + | Commercial (discontinued?) | +|
S5 Systems | +jPresto | ++ | + | + | Commercial (discontinued?) | +|
Plumb Design | +Condensity | ++ | + | Commercial (discontinued) | +||
4th Pass | +SourceGuard | ++ | + | Commercial (discontinued?) | +||
CodingArt | +CodeShield | ++ | + | Commercial (discontinued?) | +||
Software4j | +Obfuscate4j | ++ | Commercial (discontinued?) | +|||
JAMM Consulting | +ObfuscatePro | ++ | Commercial (discontinued?) | +|||
JDevelop | +JSCO | ++ | Commercial (discontinued?) | +|||
4Fang | +JMix | ++ | Commercial (discontinued?) | +|||
RetroLogic | +RetroGuard | ++ | + | Commercial (disappeared?) | +||
Helseth | +JObfuscator | ++ | + | Commercial (disappeared?) | +||
Vega Technologies | +JZipper | ++ | + | Commercial (disappeared?) | +||
JProof | +JProof | ++ | Commercial (disappeared?) | +|||
ChainKey | +Java Code Protector | ++ | Commercial (disappeared?) | +|||
2LKit | +2LKit Obfuscator | ++ | Commercial (disappeared?) | +|||
WingSoft | +WingGuard | ++ | Commercial (disappeared?) | +|||
HashJava | +HashJava | ++ | Commercial (disappeared?) | +|||
GITS | +Blurfuscator | ++ | Commercial (disappeared?) | +
+All trademarks are property of their respective holders. + +
rTM{9NKJ0$HPxKq?tf&}y)z(bH;Z`3;f^1RFS zn?O9?sJ3UO=S)h#gV-(L%~rSmlB6cdJ0O&Ny9hu4oqa^BTbH1RDc&dIaRL|R_B|y8 zWu}O$Kl#Bj0GvG5-=j6H4A%6bggYgb0Enc`z1VmFgd|Y|d}%Py0j;UOa=gDA04}>> zXE|r6i7}JZ+VP=H+wT716;GARrHcWfTq$XOQ-uqg=d`eS4!zYiuAW@eT5muAD$kX$ zalVYXjb)rT+QZ7R9#)R`VcLno+TgFh{QiOKUi*c=qXouiSjszD(}sp;Q7kY%F2h&UtM8z(&k( zs(@o^a?@8ns+a%p_Wn_P<6_KVhojZ4KiKaL$`@aAE^fSY? D`g4Yfl#)IGb6W;#EN``mm zhZk_q{a0hx?gjKt8LKOECA@QR1rOZ&91i~dct&RXu6ca +jBPl^X@82 zC2s^kU@#E27#SUU^Eg&l*0AxcGIpH5iMuY?grkR7Wrm=gS_ObVZdBX%6l*scQ& xQP!&zrnu;*i20xN-IM^2$s0vs 1#|wY)e7^5=FllQGUk%^;+^ zHONQP=C g&M~tx-xhIIv)X 7cYwVzt*);B;}wKQ270)V6qB>RnOJELOmO3*O! zF8eB{mAtO}cC*^C&aqr%&V_KfF9P%K;mT-ed3+YcveAr5;G2N8-S7}5b^!3TJmZ1k zpTTPZYjH?T+Ci^_Cke(m!94*{d @Fw;6A%68k2 +_!5c5n6nauD;prsnK>lauO}0L z>{li5hEnlEg~ewf#wh`(sNaWVGa!G6 ;&3lr`GfJ^`2|3!HUu^OlFq55;6Bo5}!F^kzrtcaYgMNubyP87JqOW#7#pLo&@V z8aU_LyBAB1V`%Y5mYy$fC}X^N3K@WWW{dGA!Jrwl{V{Pb9xw3ODEWH|>2T3 u;LJ>F^&$- zxM95X $`84}r%oguFkP z%mkUXtcHac>3~e46?Qi&HKP2^bQ+M?y`w3534GDGG2>9P1BR4 |1;#;Hrz6_M!*}x_3fi z-fh&{T@sHG_DoHdnRv8O>pWR>A~f_f*sOK#knm{%k4pG8pj(@@_Ggk@Zr72u+9W~p z-O+rTr4g =`FWW+h0-r9DBj9R@*rD2jDr h)U?~u zJy{tL;SfcEgvl_m17tM`Yx7ZQ6?54rMr4~5!9P|;iIQjdIbjY@>;S(#me)B%h4D)Y zwvDMM`Vz2)QE|aUHit8@i7@tFpb$j(3gk4U-yJP#6Qe8BiRH p(8>7nR<7$_#R(My~Faj5{P8iNT5;cJc|i1xdVVJ030RY7o0X+1NZDMYtlfr zArtO+YZr-urZ1m1bS VoZT4#63nco=o5e$nQ35V4zMOFF6F4k^Fib=xJCAG(e+~D zbwD8mfJh#4EA^g(Y_qGKnIypfAOoTV0HC5ZgJ;WYW>LfBm|X?{$k`$kW&o29NhZ1Z zWcrw01{f&w=)UYZkU70^Ts|qR@iXzjOfw)^yNquqGOTtbnMriQ{0S1Vnvt0TW|sld z>o#_Z&ZpKSp;2wWm1b{L+k)^ Px}jY&j7RCr$PoO^s-Rh7rT>zw<{`zFn!X=&P~4dqc X-MsGm-m~V9bMCqK zrh&FlQa+!V-{+Iu?7i37d+l}BUi-K9IXCb+Ku33Tu)Vwa*Bw1A>vQYdds<%Vl9!a} z=xJHs(bN3vj_&5*OI-4Q3+>%420%wo%f~u;nxAOzZZ2`kFMnYUGO``rEhQa2Et@-f zT0Z8~8!vm|G~l!=Ac6(Z+SvJhpjSk0bjmM#T`sb+dL!r&r!P>u@6!p-@dRFLv^I9q z(bG(8V;8D?0`!;d-OcOTn!0}1(bLiZx<*yb7GV~u#r9P)uIM2Vc7SYbZS36D-rcee zVYw B_3oAg>ijwdh;Fly=w&E9?CB*1qcTle=?T0d{4b*HMX1pFcb0^(?^ z3Mi;5KwLyN8>TEWO!?Z!SO4x?05x@m-rjxTG@M>9emxi%u#NSdKdk#uI%WNn=`kAo zK@(rVL{&*8m2}b~nY3-?^%|I71CK`#LrBEZ#G`4_DQlPMk()koap!F!uaBvn7A-ou zTXL80a$r?;UEyVQi%Qp9X~jyb28%pWP~z3{ssQCP3#4jx0hO}~02nwFq5oin;ogW2 z_r-{eB_%qMQo|H6Okv;7(FgkWg&zhs0b8dSbJ}ovVsQR#?Lb)3w=YcJzOb|S-OX13 z^%r<34*3Yp@S~t3gK-%@njjuYi6ftpwVcoO2 etF{X$|QVbr7aNfn$EV;Ov!9x+^k@{u;*hNU7>nT;o_US-ZXnE!Rf-Z8@Ro@ z*`-yX>cGvHy=z`JArRLaGoGwsYp7nop{w6ITUWnzHeSDxX*)(frw=ZB*Suh;I&d>& z*~)Zd+6^osCO~_4^ZVn`)YU6nYFXJ*oAKd{_hvj<)ZW)*-TUgLpx7$~#a`CEuRhau zjC{ttD_d%HWlJsbXzJ?r?&c5J{o7+tC#H44_U>ldn!2>TyQM%xzLic{b9{b7&$*yd zN-F#^G7w{YIFT13YUUQo6(4D!X~P^qPz#xVZW(2j0R|68m>5as$ +}_h%Do7WqE3(1U`EX+9DKFbN0<3Ip>^#uX({ic8JwS;a zqZN>^w>5SCGq`k;Q-M=v;0%7a<-#?wc)=f>qGF#9n1Via-I_<=2yn||YadaSwNBe> z9X1pYf!!^uA31Nn5W8jL+HH!w0Z5ZguL<}g7hk*L@r^In*~#LRZ*qep{)@aGaoqyf zfbxb<-?g; TbYU !BRF!2<6je2k*uMlOH%}!llRjN!QsVJwlBf3!&^sJKftpYOi|3USDh>dUw)A*< zWbktOoM0DILs3k__SheF{)J@?RjgY+hj1*3s;Wl-!-)&Of9fE&-v68ie5QCk_Vci0 z+R_5QN7gN$!-m!Ml$Qk5Kt)7co~f#$3YL?@iij9OhLftQilyMxxp5i5vM+M!tB7bK zm6o6U{(0_wY%hvx!0Qo9m3T5uDy_PtzCu2J#bV~qECEo ( z*!pJ1GlVJUBaXh7Q_j`jb~MGZP}4xhqY1jU?Wd%`r|Xu_5kqX1Jh_t{k0gmD((;bR z1)N +xL~f#tSBUzw%Fe{!5^PHB0ulmP5sPLuDjw~0Lgg# z VqSGI=gzBe-LiK$ z%;0E@GtUU&^%!{>*WhTBfzcTAYKjT?Jlxg2n+G<($Y at*7CU;<90#%q(Rpizk9tv}CV1m(b0!67VE8x8Owyv4^#1bhE z4~3}?6;K%PG9F2AWH>@)S&&eX-@QHCcJ*^;FwD$~0!+ieW4e^uMLrJ}dl^OJX&@Wp z3`1yIGK){X?L2O}dpq}Uevu7p>RsdhxbrXka^qf1`*@IOJVnd0Gx&$Amf$fB`bMJs z>rb}w#)Xx9@jc62BMgnjXzlm|i|1AFg?BF_o=o%8ho5KlxifkHn-&4~GS5x;1X#JK z+EqCmOYyB=Jwxq`LO!)&N#6AS^WJAkrY*j8-D*cR$!Bie#KFO^-Je3xXR>7e46eU= zDK+KxQ|tZx6MXfKZCtf_K4Z}&4{qMa;8>J*G%n!7Z$6vxXp*npxs4}w^b$#=C<=H9 z75f>Ph!gbZKf~~l!&PmFie%TiVc0QAL|DJFj&I-lj6St{KsKzY2jH&mJ$mbdJLF?; zIfpAQn2X0W^r0>L 5dh>ZLz>(oFiInA*(`jW{ zLzRB`&6RTYoDc!O$)@Le_1}N?q*Rmy`0O=r0MJA-Exp4L+JEybHK9UXx?qL`eI^TM zl>z8Cez9GCzwH3mU%iyIOK0gsG%3G*;zjOxY_GegWRy9nOs=@VM|D|{;qe$?d(UkT zJ;&c(*5G;^z&o23^8CRO?&{vd+b^!iG!0s>T+EAo pg zucicmLqih;eI_*_+mkXIWjK~(Xe{Qki)6~8yx31^p&t?Oc@4bgv3Y^llV4X9^zx|< zOY`b3JAXFa&m3ag?g2(7;*=Hn?O2Smw7!zBynh8jf7VRf_Y87(_a1I|?=s$X$wC0C zLvZ!Q^*s9YLE_1DUjLaZCzJiD%l3Znmj8Nqlz1}D{{9L5*(1AbY66rN`gG5sQH~6U zNm+_%+VWp~_ZzwH+Y@~HdylEdWAMqpIge!xRr&n`N`4Bx>CZ>>hTFGLTIj=T8l=*e ze(WvhaMfxzOr4Pah9UG0hk5v^gSzv;Q3l6igri9g4@Y!%Wf8Ws+wy5kS#$2pjB(wD z?Ry5ODKF4vXI24r2r~@PL^AD2$mTDRz@Zgu6~(4bE*)MTi$hWgfIN)3GEw>NYm0;tXNb{ zd68ecwjGd>Z~|w6xNhWlV_tuQV=*l+_Dj&`n9kmI#LD`_F(D#X877xAlLzR0azF88 zT9%(_Z!&(bNiwB!%_R-2Us*>YnZ`5?$2jWjsy0m$5t6Ai_iX&D%q>_h^KBAKS}@ zHT7=)4YNuq40>hT?tb7LJf?wVsm!e@VXhNKhR0)a+k-pY4OTVVKY5`VJcdD1Ew|k9 zn`b#X9+#hd_A<9WKn@Rud3gK5OrI}nkD$+#SRze2?YvW{Hlgu(OvDgi5)I8QsM-|; zPRucE1`fcJyZZUY-A}Xp%qp(DXdVFP%q_ 6Pe=H1*G^Z5T$q`%^I;f5!0%ybG mLWQ`bFa@63KKPO@v7- z!Zd_fGOe3;_Q^yvNhF?PWFn!@>>ZF_ZQRSkS*6_Yp5 nhh=RKD;=y&e>lav Xmu}yz zKlt=osVK42-}hbCpil1^kelw_&XJ)om#?VPP_bWBA(}|>$3Gv@{*kC;Hj@IsM;m69 z$sLdG;{GRI K>$;PbF;_W ca4O)#r162*~gb|-%L%YfJh?6 z+NHCpol!tEo;@9FyYf8#v2PRC-|`r9Yf6a3Q=B~~#G*MNj!wi~IZKsz%E}l#50zy> zZg}r9zVO2*XzTa`Wkr50g~jtKC@J(2OXRZ%dE37{pf`PVl`g0)Wh|1Afsv@Ha|aBu zJ*1@2F9lhuGUX=HI~-y6p;3m$qgqiMkowwEYAXr>ba*@_y~7dCt}8$0`u+XmnoL _2kVRo6EQ&^NQ8JY zt!GpgyYj>1F@0+Hpo~n!STL)MrS&s35>Ls%NHlYzsA Lp2 z_Y9DB&PL``6?1TKf dWs05l6~#Wk oNB0uN+RhQ+_9_v z*8ZXL-e4deINn9C2C9hPYf7lt|Kw{uxhe7Et*ahRr9GF5Xx>v@2QTZ Yc? zUXXy@&QGsf{m9^P)H~&vRu9g+G1J!Ad1rffa~fnliXVugS|=i_74_l-X2m`^Rncce zdD6ZiAgXah7O8SUCWhPccCxInSzw2V6o4ibHiG;RrvD|sX^+8^C)m;5;%#l}Ogdi# z|GBCbxlb!_ALD$ft*PtZI(nMDDB9Z8m1^&4{(vC2DVXlt70zr_`Mb8J&hNMPw0PSZ zJCp8MJuT9D3g0_B5lpKG1GF}EIp2_16C|ywNdQ%~+#@lE_PG30#Ez#bX?2*6 hV1PFJE%P+Eue4gY4~BA);nPl=?b-sQRoyt^!mV(Y zfP&H1*qO!|>vUk+H@V|NL0vmaHmZV6Fdeasvm;q~&G@h*{@PRQ %;kf=Za*{7IM7Yt#Ctu8zIz*!KdHSuY(vYncs1c%u5goPU>L)B*5`#=QSNw zP2gl}&Q|CIXjKu3+kKw?SaI47tf*roo)qOU3gWJD1sF%<@l1te8y{Ebw-3hLn*>Nd zN=E*){xc4E9T+(Cy^gk~&Jlz!BeoBM6G~NYX>IJZzmlM8spG+IO + + + + + + ProGuard Downloads + + + + +Downloads
+ +ProGuard is distributed under the terms of the GNU General Public +License. Please consult the license page for more +details. ++ProGuard is written in Java, so it requires a Java Runtime Environment + (JRE 1.5 or higher). +
+You can download the latest release (containing the program jars, the +documentation that you're reading now, examples, and the source code) from this +location: +
+
Download section at SourceForge ++ +The proguard section contains major releases and updates with +sub-minor version numbers, for applying emergency fixes. The +proguard beta section contains beta releases. These include +new features and any less urgent bug fixes collected since the previous +release. +
+If you're still working with an older version of ProGuard, check out +the summary of changes below, to see if you're missing something essential. +Better look at the up-to-date on-line version if +you're reading a local copy of this page. Unless noted otherwise, +ProGuard remains compatible across versions, so don't be afraid to +update. +
+If you're only interested in individual jar files for your build process, you +can also download them from the Maven Central repository, with GroupId +net.sf.proguard and ArtifactIds +proguard-parent, +proguard-base, +proguard-gui, +proguard-anttask, +proguard-gradle, +proguard-wtk-plugin, and +proguard-retrace. + +
+
Mar 2013Version 4.9+
+ +- Added Gradle task. +
- Added more peephole optimizations for strings. +
- Improved optimization of classes with static initializers. +
- Improved processing of finally blocks compiled with JDK 1.4 or older. +
- Fixed shrinking of access widening abstract methods, for the Dalvik VM. +
- Fixed overly aggressive shrinking of class annotations. +
- Fixed processing of unused classes in generic signatures. +
- Fixed merging of classes with similar class members. +
- Added java system property
optimize.conservatively
to allow + for instructions intentionally throwingNullPointerException
, +ArrayIndexOutOfBoundsException
, or +ClassCastException
without other useful effects. +- Fixed optimization of unnecessary variable initializations. +
- Fixed optimization of code involving NaN. +
- Fixed inlining of methods that are supposed to be kept. +
- Fixed preverification of artificially convoluted dup constructs. +
- Fixed quotes for java commands in .bat scripts. +
- Improved handling of non-sequential line number information. +
- Now requiring Java 5 or higher for running ProGuard. +
- Updated build files. +
- Updated documentation and examples. +
+
May 2012Version 4.8+
+ +- Added more peephole optimizations for strings. +
- Added support for multiple external configuration files in Ant + configurations. +
- Added support for Ant properties in external configuration files. +
- Fixed parsing of empty file filters on input and output. +
- Fixed parsing of '*' wildcard for file filters and name filters. +
- Fixed obfuscation of private methods that are overridden in concrete + classes with intermediary abstract classes and interfaces (workaround + for Oracle bugs #6691741 and #6684387). +
- Fixed optimization of complex finally blocks, compiled with JDK 1.4 or + earlier. +
- Fixed optimizing signatures of methods that are marked as not having + side effects. +
- Fixed optimization of long local variables possibly causing verification + error for register pairs. +
- Fixed merging of classes defined inside methods. +
- Fixed stack consistency in optimization step. +
- No longer removing debug information about unused parameters, for +
-keepparameternames
or-keepattributes
. +- Fixed updating manifest files with carriage return characters. +
- Now removing unreachable code in preverification step. +
- Improved default regular expression for stack traces in ReTrace. +
- Updated documentation and examples. +
+
Dec 2011Version 4.7+
+ +- Added support for Java 7. +
- Parsing unquoted file names with special characters more leniently. +
- Added support for instance methods overriding class methods. +
- Added removal of unused parameterless constructors. +
- Added removal of empty class initializers. +
- Added peephole optimizations for constant strings. +
- Avoiding idle optimization passes. +
- Improved removal of unused constants after obfuscation. +
- Fixed removal of unused classes referenced by annotations. +
- Fixed simplifying parameters of constructors that should actually be + preserved. +
- Fixed simplifying parameters of large numbers of similar constructors. +
- Fixed exceptions in optimization of unusual obfuscated code. +
- Fixed NullPointerException when specifying
-keepclassmembers
+ without specific class or class members. +- Fixed potential problems with mixed-case class name dictionaries when not + allowing mixed-case class names. +
- Fixed obfuscation of classes with EnclosingMethod attributes that don't + specify methods. +
- Fixed preverification of returning try blocks with finally blocks, inside + try blocks, when compiled with JDK 1.4. +
- Fixed sorting of interfaces containing generics. +
- Fixed paths in shell scripts. +
- Fixed filling in of text fields showing class obfuscation dictionary and + package obfuscation dictionary from configuration in GUI. +
- Worked around Oracle Java 6/7 bug #7027598 that locked the GUI on Linux. +
- Updated documentation and examples. +
+
Feb 2011Version 4.6+
+ +- Added support for synthetic, bridge, and varargs modifiers in configuration. +
- Added detection of atomic updater construction with constant arguments. +
- Fixed merging of package visible classes. +
- Fixed optimization of fields that are only accessed by reflection. +
- Fixed optimization of read-only or write-only fields that are volatile. +
- Fixed handling of side-effects due to static initializers. +
- Fixed handling of bridge flags in obfuscation step. +
- Fixed handling of super flag when merging classes. +
- Fixed updating of variable tables when optimizing variables. +
- Fixed removal of unused parameters with 32 or more parameters. +
- Fixed incorrect removal of exception handler for instanceof instruction. +
- Fixed inlining of methods with unusual exception handlers. +
- Fixed optimization of unusual code causing stack underflow. +
- Fixed keeping of constructor parameter names. +
- Fixed unwanted wrapping of non-standard META-INF files. +
- Fixed filtering of warnings about references to array types. +
- Fixed overriding of warning option and note option in Ant task. +
- Improved detection of file name extensions for canonical paths. +
- Improved printing of seeds specified by
-keep
options. +- Improved printing of notes about unkept classes. +
- Improved checking whether output is up to date. +
- Updated documentation and examples. +
+
Jun 2010Version 4.5+
+ +- Added option
-keepparameternames
. +-dontskipnonpubliclibraryclasses
is now set by default. Added +-skipnonpubliclibraryclasses
as an option. +- Made processing independent of order of input classes to get even more + deterministic output. +
- Improved constant field propagation. +
- Improved renaming of resource files in subdirectories of packages. +
- Avoiding making fields in interfaces private. +
- Optimizing exception handlers for monitorexit instruction. +
- Reduced maximum allowed code length after inlining from 8000 bytes to + 7000 bytes. +
- Fixed missing warnings about missing library classes. +
- Fixed shrinking of annotations with arrays of length 0. +
- Fixed handling of -0.0 and NaN values when simplifying expressions. +
- Fixed copying of exception handlers when simplifying tail recursion calls. +
- Fixed optimization of introspected fields. +
- Fixed simplification of unnecessary variable initializations. +
- Fixed evaluation of subroutines in pre-JDK 1.5 code. +
- Fixed updating of access flags in inner classes information. +
- Fixed disabling of field privatization. +
- Fixed invocations of privatized methods. +
- Fixed updating of local variable debug information in optimization step. +
- Fixed print settings without file name in GUI. +
- Fixed field privatization setting in GUI. +
- Fixed saving incorrectly quoted arguments in GUI. +
- Fixed handling of regular expressions with only negators. +
- Fixed unwanted wrapping of non-standard META-INF files. +
- Fixed regular expression pattern for constructors in ReTrace. +
- Updated documentation and examples. +
+
Jul 2009Version 4.4+
+ +- Added new peephole optimizations. +
- Added option
-optimizations
for fine-grained configuration of + optimizations. +- Added option
-adaptclassstrings
for adapting string constants + that correspond to obfuscated classes. +- Added option
-keeppackagenames
for keeping specified package + names from being obfuscated. +- Added option
-keepdirectories
for keeping specified directory + entries in output jars. +- Extended options
-dontnote
and-dontwarn
for + fine-grained configuration of notes and warnings. +- Added option
-regex
in ReTrace, for specifying alternative + regular expressions to parse stack traces. +- Extended renaming of resource files based on obfuscation. +
- Improved inlining of constant parameters and removal of unused parameters. +
- Avoiding bug in IBM's JVM for JSE, in optimization step. +
- Avoiding ArrayIndexOutOfBoundsException in optimization step. +
- Fixed configuration with annotations that are not preserved themselves. +
- Fixed preverification of invocations of super constructors with arguments + containing ternary operators. +
- Fixed processing of unreachable exception handlers. +
- Fixed merging of exception classes. +
- Fixed repeated method inlining. +
- Fixed inlining of finally blocks surrounded by large try blocks, compiled + with JDK 1.4 or earlier. +
- Fixed optimization of complex finally blocks, compiled with JDK 1.4 or + earlier. +
- Fixed obfuscation of anonymous class names, if
EnclosingMethod
+ attributes are being kept. +- Fixed obfuscation of inner class names in generic types. +
- Fixed decoding of UTF-8 strings containing special characters. +
- Fixed copying of debug information and annotations when merging classes. +
- Fixed writing out of unknown attributes. +
- Fixed updating manifest files with split lines. +
- Updated documentation and examples. +
+
Dec 2008Version 4.3+
+ +- Added class merging. +
- Added static single assignment analysis. +
- Added support for annotation and enumeration class types in configuration. +
- Refined shrinking of fields in case of unusual +
-keepclassmembers
options. +- Added simplification of tail recursion calls. +
- Added new peephole optimizations. +
- Fixed optimization of unused variable initializations causing negative + stack sizes. +
- Fixed optimization of unusual initialization code causing + NullPointerExceptions. +
- Fixed optimization of half-used long and double parameters. +
- Fixed processing of complex generics signatures. +
- Working around suspected java compiler bug with parameter annotations on + constructors of non-static inner classes. +
- Fixed obfuscation of classes with inner classes whose names are preserved. +
- Fixed access of protected methods in repackaged classes. +
- Added options
-classobfuscationdictionary
and +-packageobfuscationdictionary
. +- Adapting more types of resource file names based on obfuscation. +
- Extended warnings about incorrect dependencies. +
- Added start-up scripts and build scripts. +
- Updated documentation and examples. +
+
Mar 2008Version 4.2+
+ +- Refined data flow analysis in optimization step. +
- Fixed handling of exceptions when inlining subroutines. +
- Fixed inlining of incompatible code constructs between different java + versions. +
- Fixed computation of local variable frame size. +
- Fixed optimization of infinite loops. +
- Fixed optimization of subroutine invocations. +
- Fixed optimization of floating point remainder computations. +
- Fixed removal of unused parameters in method descriptors containing arrays + of longs or doubles. +
- Added undocumented java system properties +
maximum.inlined.code.length
(default is 8) and +maximum.resulting.code.length
(defaults are 8000 for JSE and + 2000 for JME), for expert users who read release notes. +- Fixed processing of generic types in Signature attributes in shrinking and + optimization steps. +
- Fixed processing of inner class names in Signature attributes in obfuscation + step. +
- Improved adapting resource file names following obfuscated class names. +
- Fixed interpretation of package names in GUI. +
- Fixed default settings for Xlets in GUI. +
- Updated documentation and examples. +
+
Dec 2007Version 4.1+
+ +- Fixed shrinking of default annotation element values. +
- Fixed optimization of invocations of methods in same class that are + accessed through extensions. +
- Fixed optimization of invocations of synchronized methods without other + side-effects. +
- Fixed optimization of some non-returning subroutines. +
- Fixed handling of local variable debug information when inlining methods. +
- Avoiding StackOverflowErrors during optimization of complex methods. +
- Fixed obfuscation of potentially ambiguous non-primitive constants in + interfaces. +
- Fixed preverification of some code constructs involving String, Class, and + exception types. +
- The Ant task now allows empty
<injars>
and +<libraryjars>
elements. +- Updated documentation and examples. +
+
Sep 2007Version 4.0+
+Upgrade considerations: +- Added preverifier for Java 6 and Java Micro Edition, with new options +
-microedition
and-dontpreverify
. +- Added new option
-target
to modify java version of processed + class files. +- Made
-keep
options more orthogonal and flexible, with option + modifiersallowshrinking
,allowoptimization
, and +allowobfuscation
. +- Added new wildcards for class member descriptors: "
***
", + matching any type, and "...
", matching any number of + arguments. +- Added support for configuration by means of annotations. +
- Improved shrinking of unused annotations. +
- Added check on modification times of input and output, to avoid unnecessary + processing, with new option
-forceprocessing
. +- Added new options
-flattenpackagehierarchy
and +-repackageclasses
(replacing-defaultpackage
) to + control obfuscation of package names. +- Added new options
-adaptresourcefilenames
and +-adaptresourcefilecontents
, with file filters, to update + resource files corresponding to obfuscated class names. +- Added detection of dynamically accessed fields and methods. +
- Now treating
Exceptions
attributes as optional. +- Now respecting naming rule for nested class names + (
EnclosingClass$InnerClass
) in obfuscation step, if +InnerClasses
attributes orEnclosingMethod
+ attributes are being kept. +- Added new inter-procedural optimizations: method inlining and propagation + of constant fields, constant arguments, and constant return values. +
- Added optimized local variable allocation. +
- Added more than 250 new peephole optimizations. +
- Improved making classes and class members public or protected. +
- Now printing notes on suspiciously unkept classes in parameters of + specified methods. +
- Now printing notes for class names that don't seem to be fully qualified. +
- Added support for uppercase filename extensions. +
- Added tool tips to the GUI. +
- Rewritten class file I/O code. +
- Updated documentation and examples. +
+ +
+ +- Since ProGuard now treats the
Exceptions
attribute as + optional, you may have to specify-keepattributes Exceptions
, + notably when processing code that is to be used as a library. + +- ProGuard now preverifies code for Java Micro Edition, if you specify the + option
-microedition
. You then no longer need to process the + code with an external preverifier. + +- You should preferably specify
-repackageclasses
instead of the + old option name-defaultpackage
. ++
Dec 2007Version 3.11+
+ +- Fixed optimization of invocations of methods in same class that are + accessed through extensions. +
- Fixed optimization of invocations of synchronized methods without other + side-effects. +
- Updated documentation and examples. +
+
Aug 2007Version 3.10+
+ +- Now handling mixed-case input class names when +
-dontusemixedcaseclassnames
is specified. +- Fixed optimization of synchronization on classes, as compiled by Eclipse + and Jikes. +
- Fixed optimization of switch statements with unreachable cases. +
- Avoiding merging subsequent identically named files. +
- Updated documentation and examples. +
+
Jun 2007Version 3.9+
+ +- Fixed processing of .class constructs in Java 6. +
- Fixed repeated processing of .class constructs. +
- Fixed possible division by 0 in optimization step. +
- Fixed handling of variable instructions with variable indices larger than + 255. +
- Updated documentation and examples. +
+
Mar 2007Version 3.8+
+ +- Fixed optimization of parameters used as local variables. +
- Fixed obfuscation with conflicting class member names. +
- Fixed incremental obfuscation with incomplete mapping file for library jars. +
- Updated documentation and examples. +
+
Dec 2006Version 3.7+
+ +- Now accepting Java 6 class files. +
- Fixed shrinking of partially used annotations. +
- Improved incremental obfuscation, with new option +
-useuniqueclassmembernames
. +- Printing more information in case of conflicting configuration and input. +
- Fixed optimization of repeated array length instruction. +
- Fixed optimization of subsequent try/catch/finally blocks with return + statements. +
- Fixed optimization of complex stack operations. +
- Fixed optimization of simple infinite loops. +
- Fixed optimization of expressions with constant doubles. +
- Tuned optimization to improve size reduction after preverification. +
- Fixed overflows of offsets in long code blocks. +
- Now allowing class names containing dashes. +
- Updated documentation and examples. +
+
May 2006Version 3.6+
+ +- No longer automatically keeping classes in parameters of specified methods + from obfuscation and optimization (introduced in version 3.4). +
- Fixed inlining of interfaces that are used in .class constructs. +
- Fixed removal of busy-waiting loops reading volatile fields. +
- Fixed optimization of comparisons of known integers. +
- Fixed optimization of known branches. +
- Fixed optimization of method calls on arrays of interfaces. +
- Fixed optimization of method calls without side-effects. +
- Fixed optimization of nested try/catch/finally blocks with return + statements. +
- Fixed initialization of library classes that only appear in descriptors. +
- Fixed matching of primitive type wildcards in configuration. +
- Fixed the boilerplate specification for enumerations in the GUI. +
- Updated documentation and examples. +
+
Jan 2006Version 3.5+
+ +- Fixed obfuscation of class members with complex visibility. +
- Fixed optimization bugs causing stack verification errors. +
- Fixed optimization bug causing overridden methods to be finalized. +
- Fixed optimization bug causing abstract method errors for retro-fitted + library methods. +
- Fixed optimization bug evaluating code with constant long values. +
- Fixed bug in updating of optional local variable table attributes and local + variable type table attributes after optimization. +
- Fixed interpretation of comma-separated class names without wildcards. +
- Updated documentation and examples. +
+
Oct 2005Version 3.4+
+ +- Extended optimizations: removing duplicate code within methods. +
- Extended regular expressions for class names to comma-separated lists. +
- Now automatically keeping classes in descriptors of kept class members. +
- Added verbose statistics for optimizations. +
- Added boilerplate Number optimizations in GUI. +
- Fixed
Class.forName
detection. +- Fixed incremental obfuscation bug. +
- Fixed optimization bug causing stack verification errors. +
- Fixed optimization bugs related to removal of unused parameters. +
- Fixed exception when optimizing code with many local variables. +
- Fixed exception when saving configuration with initializers in GUI. +
- Updated documentation and examples. +
+
Jun 2005Version 3.3+
+ +- Extended optimizations: making methods private and static when possible, + making classes static when possible, removing unused parameters. +
- Made file names relative to the configuration files in which they are + specified. Added
-basedirectory
option. +- Added
-whyareyoukeeping
option to get details on why given + classes and class members are being kept. +- Added warnings for misplaced class files. +
- Improved printing of notes for
Class.forName
constructs. +- Implemented '
assumenosideeffects
' nested element in Ant task. +- Improved processing of annotations. +
- Fixed reading and writing of parameter annotations. +
- Fixed various optimization bugs. +
- Fixed wildcards not matching '-' character. +
- Fixed wildcard bug and checkbox bugs in GUI. +
- Setting file chooser defaults in GUI. +
- Leaving room for growBox in GUI on Mac OS X. +
- Properly closing configuration files. +
- Updated documentation and examples. +
+
Dec 2004Version 3.2+
+ +- Fixed JDK5.0 processing bugs. +
- Fixed optimization bugs. +
- Fixed relative paths in Ant task. +
- Improved speed of shrinking step. +
- Updated documentation and examples. +
+
Nov 2004Version 3.1+
+ +- Improved obfuscation and shrinking of private class members. +
- Added inlining of interfaces with single implementations. +
- Added option to specify obfuscation dictionary. +
- Added option to read package visible library class members. +
- Extended support for JDK5.0 attributes. +
- Fixed various optimization bugs. +
- Modified Ant task to accept paths instead of filesets. +
- Fixed two Ant task bugs. +
- Updated documentation and examples. +
+
Aug 2004Version 3.0+
+ +- Added bytecode optimization step, between shrinking step and obfuscation + step. +
- Generalized filtered recursive reading and writing of jars, wars, ears, + zips, and directories. +
- Added support for grouping input and output jars, wars, ears, zips, and + directories. +
- Added support for applying mapping files to library classes. +
- Removed
-resourcejars
option. Resources should now be read + using regular-injars
options, using filters if necessary. +- Rewrote Ant task. Input and output modification dates are not checked at + the moment. Minor changes in XML schema: +
+
+- Filters now specified using attributes. +
- '
outjars
' now nested element instead of attribute. +- '
type
' attribute of<method>
element no + longer defaults to 'void
'. +<
and>
characters now have to be + encoded in embedded configurations. +<proguardconfiguration>
task no longer accepts + attributes. +- Updated J2ME WTK plugin, now customizable through configuration file. +
- Updated GUI. +
- Fixed various processing bugs. +
- Fixed ReTrace parsing bugs. +
- Improved jar compression. +
- Updated documentation and examples. +
+
Mar 2004Version 2.1+
+ +- Added support for JDK1.5 classes. +
- Added additional wildcard for matching primitive types. +
- Added possibility to switch off notes about duplicate class definitions. +
- Fixed use of multiple filters on output jars. +
- Fixed option to keep all attributes. +
- Fixed various Ant task bugs. +
- Updated documentation and examples. +
+
Dec 2003Version 2.0+
+ +- Added a graphical user interface for ProGuard and ReTrace. +
- Added
-applymapping
option for incremental obfuscation. +- Added support for filtering input and output files. +
- Added support for the J++
SourceDir
attribute. +- Improved detection of
.class
constructs. +- Improved handling of misplaced manifest files. +
- Improved implementation of ReTrace. +
- Worked around String UTF-8 encoding bug affecting foreign characters. +
- Fixed exception when ignoring warnings. +
- Fixed various Ant task bugs. +
- Updated documentation and examples. +
+
Aug 2003Version 1.7+
+ +- Fixed various Ant task bugs. +
- Fixed ClassCastException due to explicitly used abstract classes with + implicitly used interfaces targeted at JRE1.2 (the default in JDK1.4). +
- Fixed
-defaultpackage
bug for protected classes and class + members. +- Fixed ReTrace bug when retracing without line number tables. +
- Worked around zip package problems with duplicate out entries and rogue + manifest files. +
- Added work-around for handling malformed legacy interface class files. +
- Updated documentation and examples. +
+
May 2003Version 1.6+
+ +- Added support for Ant. +
- Added support for the J2ME Wireless Toolkit. +
- Added support for reading and writing directory hierarchies. +
- Added option for specifying resource jars and directories. +
- Added support for wildcards in class member specifications. +
- Improved handling of the
-defaultpackage
option. +- Improved stack trace parsing in ReTrace tool. +
- Fixed processing of libraries containing public as well as non-public + extensions of non-public classes. +
- Fixed examples for processing libraries, midlets, and serializable code. +
- Updated documentation and examples. +
+
Jan 2003Version 1.5+
+ +- Fixed processing of retrofitted library interfaces. +
- Fixed processing of
.class
constructs in internal classes + targeted at JRE1.2 (the default in JDK1.4). +- Fixed
-dump
option when-outjar
option is not + present. +- Updated documentation and examples. +
+
Nov 2002Version 1.4+
+ +- Now copying resource files over from the input jars to the output jar. +
- Added option to obfuscate using lower-case class names only. +
- Added better option for obfuscating native methods. +
- Added option not to ignore non-public library classes. +
- Added automatic
.class
detection for classes compiled with + Jikes. +- Updated documentation and examples. +
+
Sep 2002Version 1.3+
+ +- Added support for wildcards in class names. +
- Added tool to de-obfuscate stack traces. +
- Added options to print processing information to files. +
- Added option to rename source file attributes. +
- Fixed processing of implicitly used interfaces targeted at JRE1.2 (the + default in JDK1.4) +
- Fixed processing of configurations with negated access modifiers. +
- Fixed duplicate class entry bug. +
- Updated documentation and examples. +
+
Aug 2002Version 1.2+
+ +- Improved speed. +
- Fixed processing of classes targeted at JRE1.2 (the default in JDK1.4) + with references to their own subclasses. +
- Fixed processing of static initializers in J2ME MIDP applications. +
- Fixed processing of retrofitted interfaces (again). +
- Added more flexible handling of white space in configuration. +
- Updated documentation. +
+
Jul 2002Version 1.1+
+ +- Added automatic detection of
Class.forName("MyClass")
, +MyClass.class
, and +(MyClass)Class.forName(variable).newInstance()
constructs. + This greatly simplifies configuration. +- Added options to keep class names and class member names without affecting + any shrinking. They are mostly useful for native methods and serializable + classes. +
- Fixed processing of retrofitted interfaces. +
- Added handling of missing/invalid manifest file in input jar. +
- Updated documentation and examples. +
+
Jun 2002Version 1.0+
+ +- First public release, based on class parsing code from Mark Welsh's + RetroGuard. +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/drop1.gif b/docs/drop1.gif new file mode 100644 index 0000000000000000000000000000000000000000..426d8564123ebdfa0ff1cc6cce776cfc938cebb3 GIT binary patch literal 803 zcmZ?wbh9u|oWRJzaEyUr?b@}=moHzsbm`o=bEi+AK6UEU-rnBM&d$ch#@gE2%F4>} z^77Ks(trQ{{rU6f*RNkce*F0M?c0|xUp{^M^x?yYckkZ4dGqGgt5?sSJ$v%x$)iV) zZr!?d(|epKY#rA@%{VvFJHcV{`~pVr%xY0e*Ey^!@GCy-oAbN z=FOW|uU@@;`SRJbXOAC0e)#a=g9i`p-@kwF-n~0_?%ce2Gs92=Iv@vw;(~$wUxS#r zjlH5OD?0}#7q?a)&xDDSCQq3 $P>&)zuN3v+kbSy88P1gu`_PuM*wa#dMVp zOh`;*>y_%1%sDZ2^}=;`cUOFVb@%l4_4oHTFmucK?AY+|aEGvV+?gF4lX;7CQ&wy| zbdZ@tP{pUi(Xs9Mc~PfsIp1AdUS3`iygKgeuC1@HZ%95p&v*B>x3_l`zh3v@rg1Bq zww8UyMW&|i$0uT4BF^pE`T6;U#oqJ%_U`)n`o`w$`{(xV{{H^K;cj_ N8yOg^ E0oW#P7ytkO literal 0 HcmV?d00001 diff --git a/docs/drop2.gif b/docs/drop2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6075421d8333ffca319124594b8042af52ba26f GIT binary patch literal 620 zcmZ?wbh9u| ^Xu2IA3uJ4`}Xb2moJ|_efsd>!@GCy-n@D9>eZ`f&z?Pb^5oH@M|bYr zxpnK-wQJX|T)A@T(xo$J&Kx*!VBfxdn>KA)wQALh6)To4TefJ?qDhk`O_(sDudlDB zrlzc{?C;;dzkmP!`Sa)Z@87?E{rdUy=Z_yhzJLGz<;#~(pFVy3`0>Ms4{zVTee>qc z%a<>oJ$v@}@#BXNA3k{S;Qsyl_wL=hbLY;@n>RBIO`rpEHYhF_*e^DS8XF4e>FV&9 zi;Ef==<(`USxAZ*3GnIIT3ecl8uIHZDOgL38yoPcDcM??iwf$osyfO`nF#T-GdtN> ziW}*3urS!lm {PpwuzxO}>3QJswJ6Ol^QuR)HK%#RShdfh>#KuPso!sh9don&M z9PgKN4q~wkdg3-&DmX2sb7Si9Ne2GMY^J}H^R2zL eaJn&mKK` zbnDiw8#iuj+O%oWqDBAz|Nr~<@9*EgfByXW_3PKqpFe;6`0@Sw_YWUFynXxj<;$1P zo;`c`@ZtUY_cOqN4u}D=i-FZ-!R4Hrr6NIxGrg014=po1mB J;m=YBnnB*pDvHYq4I?x&bsIX+_ literal 0 HcmV?d00001 diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3923ec14ef4a57a612bc398a3569c26f7904397f GIT binary patch literal 7406 zcmeHLX;)Lp*4|+Z7zi0i0!bJ`m}dgC;=rT`B7=w#gd~I^2_ZlrVJ0L*85Cr+)z%gj zwG~AWK}84+NVh%D^K5tjf&1}(xa;+;3Iq}D+x_LP`>yqNt#wj4=RAAYu6^p%+0O$& z0BeYd0MrxVhBH7c0C;(=of83mM%P?iR?ii-0G&*L0E9s%P=pR_XKoIwo%xsW?Elo% z6iiM|!tL9);nuBNFg7*@*RNlPYuB#9l`B`^^5x5L@!~}oxiA73E?j`~=g-4yue}Cm z&YXc)UwsvZhlgQsa1i?Y`{CrtlhD)C1ILdahpw(J=;-KxqeqWIdwVX#(9qBTb#-;1(P*HirUt63tD&;85-KVxpuD^s _6F=fmN{hvCqnLvZlmK{#;W0AyulK}JRfq^GCD-o1Na&z?PyoSY1aiHWdn z+ct=aiGj$-Ncioy-{8rUC-C#nKf{kd{s@7Af$;tJ--Adj27iBl`1adx!PnOpzW(}a z`0~py!Q0y#KL7l4@bvVAPe1(>xLhuL{PD-YX0zeL4?l$W-+v#NOeVbh?z`aX>I#n^ zKZdv7dJ7&sdIU>LOYr8KZ-U8W0tW{Nn46n}+1XjRfB!zr%*?>uyLaKvojWiwF#+S_ z<8brlO}KI62E6gc8*ugNRTv!|g-e$%!N|x6y#D&@aPHhWID7UioIZUTPMtahLqkI_ zFfagpeSOf|+Y2X7oPh4`Zs_dngk#5!fzfCLgTVl8ZEeun+6v9h&CuA`2=(>#pw()j zwzd}3YBf| G8vSXmO^oHF%%UQff(hcu&@x09617cd3hid3L!T) z7jklPAUiu7GBYz_|Ni~3d-rZgNJxNPyLQ2j9Xnv_)~yg58w*iUQSkfkzoWGr0l)tG zEBx}yFAx$E0zduq6a4VQ5AfZ0-+`Z>AAIx8H^Arf;j6E{0v?YCUwrWeTJK))*=L`@ zC!c%*91aIQ`sgG0;DZl<#bUvG@4W{M1_R!C=N)+a?YDtSrNYX}3VJ78V0n2NoSmIv zad8nyBoZtvEWrHyJP?UQc=+%k*xA{^g9i`b-o1M;Jw5&GrTBmQ4?U^%_NPf$N3Q?* zcP1EgDtbsD5DX2U`cn%85JdKcg`({wwD)9Re^j)^ Mbb4=}j)36ssMR4hj1U{q z%{S=SZp=C@T|=YMG<4TGCabB1>)FolJl-3*I*Vrp5dp?Fb|XVet5LgDlgZW9Y6_L6 zWi&Lk=)8;_-J$)%IHq;{Ko?KfR8Ob6c#((-JKM4{8>^M&g1HJhgXP}p$@2{e?Kh9G zW^k&T$8D^ub#Yd8ZQr-_MvvaZ5Sn>+$E&UCS}oI!)7Fj*BF%GHH3&9x8?`l6DkV`a zD~nkgYUk=BhKNKZsj|98!)R k&ozdNgX)m5xNaveJ@bk2ho6TRB~IHnwu2 zQdLEv)gc33$MJA;TJZqg`X;T~NoikZUA$5xalaSa-oo-!6G}>D_6{UxH8S9M8aspg zaYP6{;M2mOR65w9IZDK$g@!{h?d PU-;~A~01+heGWn)LIaHeRO?z;Alpgx=<06tq=?I 1_R2~%y`e>awEJW< z!gsjSoD`)ii%0HH=S+;>O0ULvO6Bt8ln@y#OG{)#5*ZDk<8}7nXJBMe9A(AJraWQJ zL`Hhr^(q{XTDCBqH+RHj5=jW9a%Ck&%i fze$>laHqWqbuiHx!9*HWAizLlXS zJ5^DYgk?#Qq}Y~7s-`j7p8UW*^awm%ofRb#Q(o?YjIq>| 47`slQW$Hn9k{65TW^%I9ucss@URK_YZ0CCPxTmJwnsCTo;@K<| zNXsiJu5MhOe=k}S9vYR5u$V7AkdbyRIWgg4`Tmf0PP30)%JuZ|1NMbUJY~@%xk^oE zwR-!73NW5zD;3S=PTabFWi;X92=Qi6JDcfYoqP=qFeO+TW|K SZ@&fwsdN$H4%8E>fbH>wBMib&k99I3W&3Ac!l)=N(7);T+ zdH4iInqM$hm7IVRnx1+kF(F=gcNoRPDOt@Y?R21C?>p#MQ`f9N7A(N;BeYQ+N+n0o z0BFXE369xO26wu 9PA!IU+ZX7RIs+ z^vX;RqDpRKyLWZlF(=2W+IqIZFU;Z{;eF7ewvrUg7N8v^A60t!bEbtw$s;j(yX=&e zHFZsG{1ZbP@ZhC!l9v=M9+^EXoX(xf%@xk%<(n2CA-IE+T8pC@*a%1EKfRKOHWd-t zu}~$32SD48l?{4#5ga|*i09!bBu2F(+T@Cs7exyTqD8R;ZB{acqca7=yIz2!Ni@|~ zI>^zcOOUQe3B@HgGKJC!Z&e;B7 IZT7qP2X z+E{c7xl% ;_x8{FC46oTVCfC`9C5JCJ-+;(YzFN7CF3sP>l@;Gg3mX^Z<*KT`C9T|$qP!6 zIZx|(d$N{COI|H`Udub?sb1(vK*u^ywLvGAhGMm}zrs`h+x+yea?`Z5v~_;EJ9)R6 zpT@_>!_J*MVf*&&W{w&j9&YBSp`oE>o*En+Z04$%r&>5F=BGYBKF@Jf%uhFRQ#Us^ zGe5=L6!TJ4VVb!qg+ej&Q!<$hXj_9n ;CV4V+OLa5Pvi`B=x+|4xJSY^hZYaN0||44?PcfxIMBrxGSKeqcbSDrw?OJ zKiq&wi|gt1HR#*C+Pn??V_l&U0|=0|4oD35H?%gpyVbMm8`#aBdc=eJkc&%efV9w~ zx+a!}PE)ICbPcnCqciviW5BA1f*3=y77;em7Dq=%g~E}_KwQcg6h5#P!?2Ofpg7lb z4n{ZDvVy|-G)iq9N9P-aJe)=&95go7kheIL*}CjK-s~MvMpTf !m+2bsrJ+&P^=$$Df<#KGNqGDEXu_`XA(S8Uef1fg8=FaU({~MI?bZ;B z@+QZwCcU1C@0 KL0_UaC%yp zcVtd%vbHNHGn)OvEh~J8=1?r2%@gM4PS4~QN~C4z>9KjCiP*cj?J%h9ZHi3uqIpx1 zv{a_7(lqg7EY=ut&%b&L5wZH>k}{&B6IILQZ!K6gwftuEXeiDV6)G}?Uf0ro>Y(NN zvwnA?hkJd!d$YIy-kZ;^KK%#z=~Dy2T&AI#BOcWwWPCh9<;4=JT<~E)C4}XGKWP>m z?w8i=pCDfrzjzFDse;DDW8*r-1sz`KSg%ty)F$ZSdfQy5Safu(p}$Nk|EoIrMvWZn z;}&gvW6iNy1GnhkSog*{H?AG9p1oP8w$uW+4!}A!)~7dW)0=f^tVd%l+M+>Y{rQi+ z@mP1Z=*?JTw&=?iP1&L+V=Z~3j+~mBYSxhPHyUflmhUpwiLpkEzrUOHU^<=t+&6Z! z=KHtKyS_~S{_`KoK$wun^YIaet-6={Ww71%aWb-fgmQF6et< >9__^)ht-p6x_4my%Ya&yQp%yQY4 z Ohf1CDYRs^P-I_L7?9w$qacL6pGnOK1Fm(rt=HkqWRF7`@hm@p(mmF) zlF;x-!8Rh@8&9B=Yabg;u!(a_$;GFri87qxlUxrL;s5_cT= o!k%` literal 0 HcmV?d00001 diff --git a/docs/feedback.html b/docs/feedback.html new file mode 100644 index 000000000..dd9c5091b --- /dev/null +++ b/docs/feedback.html @@ -0,0 +1,118 @@ + + + + + + + + ProGuard Feedback + + + + +Feedback
+ +By now, I've invested an enormous amount of time in ProGuard. You can +help by providing feedback! If you have problems, bugs, bug fixes, ideas, +encouragements, etc., please let me know: ++
+
+- Through + Saikoa, + we provide professional support for ProGuard. If you find ProGuard useful + and you would like to have some professional backing, this is the place to + go.
+ +- The help forum (at SourceForge) + and Stack Overflow are common places to ask questions about + any problems you might have configuring and running ProGuard. At this + time, I can generally only assist other open source projects though. If + you're working on commercial software, please consider our professional + support above.
+ +- The open discussion forum (at SourceForge) offers a place + to share your thoughts and discuss new ideas.
+ +- The bug + tracking page (at SourceForge) allows you to submit and consult bug + reports. Please make sure the reports are complete and concise. If I can't + reproduce the problem, I most likely can't fix it either.
+ +- The feature request page (at SourceForge) allows you to + submit and consult feature requests. I generally have my own road map in + mind, but this is the place express your interest in new and existing + ideas.
+ +- The download section at SourceForge and the project page at Freecode (Freshmeat) offer the + possibility to subscribe to the announcements of new releases. They are + the most efficient way to stay abreast of the latest developments.
+ +- For anything that doesn't fall in the above categories, you can mail me + directly at + + + +.
++I can't promise a swift answer, or any answer at all, for that matter, but it's +always great to see constructive comments. +
+ +ProGuard isn't a typical open source project, in the sense that I am +not looking for code contributions. Developing on my own allows me to +do things my way, without the overhead and compromises associated with larger +projects. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..59499b0a0 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,92 @@ + + + + + + + + + + + +ProGuard + + + + + + ++ + + diff --git a/docs/license.html b/docs/license.html new file mode 100644 index 000000000..d1077b8e7 --- /dev/null +++ b/docs/license.html @@ -0,0 +1,61 @@ + + + + + + ++ProGuard is a free Java class file shrinker, optimizer, obfuscator, and +preverifier. It detects and removes unused classes, fields, methods, and +attributes. It optimizes bytecode and removes unused instructions. It renames +the remaining classes, fields, and methods using short meaningless names. +Finally, it preverifies the processed code for Java 6 or for Java Micro +Edition. +
++Your browser doesn't support frames, but that's cool. +
+You can go straight to the main page. + +
+ +Copyright © 2002-2013 +Eric Lafortune. + + +ProGuard License + + + + +License
+ +ProGuard is free. You can use it freely for processing your +applications, commercial or not. Your code obviously remains yours after +having been processed, and its license can remain the same. ++ +ProGuard itself is copyrighted, but its distribution license provides +you with some rights for modifying and redistributing its code and its +documentation. More specifically, ProGuard is distributed under the +terms of the GNU General Public License (GPL), version +2, as published by the Free +Software Foundation (FSF). In short, this means that you may freely +redistribute the program, modified or as is, on the condition that you make +the complete source code available as well. If you develop a program that is +linked with +ProGuard, the program as a whole has to be distributed at no charge +under the GPL. I am granting a special +exception to the latter clause (in wording suggested by +the FSF), for combinations with the following stand-alone +applications: Apache Ant, Apache Maven, the Google Android SDK, the Eclipse +ProGuardDT GUI, the EclipseME JME IDE, the Oracle NetBeans Java IDE, the +Oracle JME Wireless Toolkit, the Intel TXE SDK, the Simple Build Tool for +Scala, the NeoMAD Tools by Neomades, the Javaground Tools, and the Sanaware +Tools. + +
+The ProGuard user documentation represents an important part of this +work. It may only be redistributed without changes, along with the unmodified +version of the code. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/main.html b/docs/main.html new file mode 100644 index 000000000..988d87ca7 --- /dev/null +++ b/docs/main.html @@ -0,0 +1,104 @@ + + + + + + + + + +ProGuard Main + + + + +Main
+ ++ProGuard is a free Java class file shrinker, optimizer, obfuscator, and +preverifier. It detects and removes unused classes, fields, methods, and +attributes. It optimizes bytecode and removes unused instructions. It renames +the remaining classes, fields, and methods using short meaningless names. +Finally, it preverifies the processed code for Java 6 or higher, or for Java +Micro Edition. +
+Some uses of ProGuard are: ++ +
+- Creating more compact code, for smaller code archives, faster transfer + across networks, faster loading, and smaller memory footprints.
+ +- Making programs and libraries harder to reverse-engineer.
+ +- Listing dead code, so it can be removed from the source code.
+ +- Retargeting and preverifying existing class files for Java 6 or higher, to + take full advantage of their faster class loading.
+ ++ProGuard's main advantage compared to other Java obfuscators is +probably its compact template-based configuration. A few intuitive command +line options or a simple configuration file are usually sufficient. +The user manual explains all available options and shows examples of this +powerful configuration style. +
+ProGuard is fast. It only takes seconds to process programs and +libraries of several megabytes. The results section presents actual figures +for a number of applications. +
+ProGuard is a command-line tool with an optional graphical user +interface. It also comes with plugins for Ant, for Gradle, and for the JME +Wireless Toolkit. +
+
+ + +ProGuard now has a sibling optimizer and obfuscator for Android: +DexGuard. It +focuses on code protection, with additional features like string encryption +and class encryption. It directly targets Dalvik bytecode and streamlines the +Android build process. +
+The following sections provide more detailed information: ++
+ +- Main: this overview page.
+- Results: some results obtained with + ProGuard, including timings and memory usage.
+- FAQ: answers to some Frequently Asked Questions.
+- Manual: the complete ProGuard user + manual, with examples and troubleshooting tips.
+- Quality: a discussion of the (excellent) quality + of ProGuard's code.
+- Screenshots: some impressions of what ProGuard looks like.
+- Testimonials: what users think of + ProGuard.
+- License: ProGuard is free, under a GPL + license.
+- Downloads: download the ProGuard + package yourself.
+- Feedback: tell me about your experiences, or + learn from others on our forums.
+- Acknowledgements: people who have been + helpful.
+- Alternatives: other Java obfuscators, + optimizers, and shrinkers.
+
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/ant.html b/docs/manual/ant.html new file mode 100644 index 000000000..0837bbb43 --- /dev/null +++ b/docs/manual/ant.html @@ -0,0 +1,644 @@ + + + + + + +Ant Task + + + + +Ant Task
+ +ProGuard can be run as a task in the Java-based build tool Ant (version +1.6.0 or higher). ++ +Before you can use the
proguard
task, you have to tell Ant about +this new task. The easiest way is to add the following line to your +build.xml
file: ++ +
+<taskdef resource="proguard/ant/task.properties" + classpath="/usr/local/java/proguard/lib/proguard.jar" /> +++ +Please make sure the class path is set correctly for your system. +
+ +There are three ways to configure the ProGuard task: +
+
+These three ways can be combined, depending on practical circumstances and +personal preference. +- using an external configuration file,
+- using embedded ProGuard configuration options, or
+- using the equivalent XML configuration tags.
++ +
1. An external ProGuard configuration file
+ +The simplest way to use the ProGuard task in an Ant build file is to keep your +ProGuard configuration file, and include it from Ant. You can include your +ProGuard configuration file by setting +theconfiguration
+attribute of your +proguard
task. Your ant build file will then look like this: ++ +
+<taskdef resource="proguard/ant/task.properties" + classpath="/usr/local/java/proguard/lib/proguard.jar" /> +<proguard configuration="myconfigfile.pro"/> +++ +This is a convenient option if you prefer ProGuard's configuration style over +XML, if you want to keep your build file small, or if you have to share your +configuration with developers who don't use Ant. +
+ +
2. Embedded ProGuard configuration options
+ +Instead of keeping an external ProGuard configuration file, you can also copy +the contents of the file into the nested text of theproguard
task +(the PCDATA area). Your Ant build file will then look like this: ++ +
+<taskdef resource="proguard/ant/task.properties" + classpath="/usr/local/java/proguard/lib/proguard.jar" /> +<proguard> + -libraryjars ${java.home}/lib/rt.jar + -injars in.jar + -outjars out.jar + + -keepclasseswithmembers public class * { + public static void main(java.lang.String[]); + } +</proguard> +++ +Some minor syntactical changes are required in order to conform with the XML +standard. +
+ +Firstly, the
#
character cannot be used for comments in an XML +file. Comments must be enclosed by an opening<!--
and a +closing-->
. All occurrences of the#
character +can be removed. ++ +Secondly, the use of
<
and>
characters would +upset the structure of the XML build file. Environment variables can be +specified with the usual Ant style${...}
, instead of the ProGuard +style<...>
. Other occurrences of<
and +>
have to be encoded as<
and +>
respectively. ++ +
3. XML configuration tags
+ +If you really prefer a full-blown XML configuration, you can replace the +ProGuard configuration options by XML configuration tags. The resulting +configuration will be equivalent, but much more verbose and difficult to read, +as XML goes. The remainder of this page presents the supported tags. For a +more extensive discussion of their meaning, please consult the traditional Usage section. You can find some sample configuration +files in theexamples/ant
directory of the ProGuard distribution. ++ +
Task Attributes and Nested Elements
+ +The<proguard>
task and the +<proguardconfiguration>
task can have the following +attributes (only for<proguard>
) and nested +elements: + ++ +
+ +- +
configuration
+ = "filename"- Read and merge options from the given ProGuard-style configuration + file. Note: for reading multiple configuration files or XML-style + configurations, use the
+ +configuration
+ element.- +
skipnonpubliclibraryclasses
+ = "boolean" + (default = false)- Ignore non-public library classes.
+ +- +
skipnonpubliclibraryclassmembers
+ = "boolean" + (default = true)- Ignore package visible library class members.
+ +- +
target
+ = "version" + (default = none)- Set the given version number in the processed classes.
+ +- +
forceprocessing
+ = "boolean" + (default = false)- Process the input, even if the output seems up to date.
+ +- +
printseeds
+ = "boolean or filename" + (default = false)- List classes and class members matched by the various
+ +keep
+ commands, to the standard output or to the given file.- +
shrink
+ = "boolean" + (default = true)- Shrink the input class files.
+ +- +
printusage
+ = "boolean or filename" + (default = false)- List dead code of the input class files, to the standard output or to the + given file.
+ +- +
optimize
+ = "boolean" + (default = true)- Optimize the input class files.
+ +- +
optimizationpasses
+ = "n" + (default = 1)- The number of optimization passes to be performed.
+ +- +
allowaccessmodification
+ = "boolean" + (default = false)- Allow the access modifiers of classes and class members to be modified, + while optimizing.
+ +- +
mergeinterfacesaggressively
+ = "boolean" + (default = false)- Allow any interfaces to be merged, while optimizing.
+ +- +
obfuscate
+ = "boolean" + (default = true)- Obfuscate the input class files.
+ +- +
printmapping
+ = "boolean or filename" + (default = false)- Print the mapping from old names to new names for classes and class members + that have been renamed, to the standard output or to the given file.
+ +- +
applymapping
+ = "filename" + (default = none)- Reuse the given mapping, for incremental obfuscation.
+ +- +
obfuscationdictionary
+ = "filename" + (default = none)- Use the words in the given text file as obfuscated field names and method + names.
+ +- +
classobfuscationdictionary
+ = "filename" + (default = none)- Use the words in the given text file as obfuscated class names.
+ +- +
packageobfuscationdictionary
+ = "filename" + (default = none)- Use the words in the given text file as obfuscated package names.
+ +- +
overloadaggressively
+ = "boolean" + (default = false)- Apply aggressive overloading while obfuscating.
+ +- +
useuniqueclassmembernames
+ = "boolean" + (default = false)- Ensure uniform obfuscated class member names for subsequent incremental + obfuscation.
+ +- +
usemixedcaseclassnames
+ = "boolean" + (default = true)- Generate mixed-case class names while obfuscating.
+ +- +
flattenpackagehierarchy
+ = "package_name" + (default = none)- Repackage all packages that are renamed into the single given parent + package.
+ +- +
repackageclasses
+ = "package_name" + (default = none)- Repackage all class files that are renamed into the single given + package.
+ +- +
keepparameternames
+ = "boolean" + (default = false)- Keep the parameter names and types of methods that are kept.
+ +- +
renamesourcefileattribute
+ = "string" + (default = none)- Put the given constant string in the
+ +SourceFile
+ attributes.- +
preverify
+ = "boolean" + (default = true)- Preverify the processed class files if they are targeted at Java Micro + Edition or at Java 6 or higher.
+ +- +
microedition
+ = "boolean" + (default = false)- Target the processed class files at Java Micro Edition.
+ +- +
verbose
+ = "boolean" + (default = false)- Write out some more information during processing.
+ +- +
note
+ = "boolean" + (default = true)- Print notes about potential mistakes or omissions in the configuration. + Use the nested element dontnote for more + fine-grained control.
+ +- +
warn
+ = "boolean" + (default = true)- Print warnings about unresolved references. Use the nested + element dontwarn for more fine-grained + control. Only use this option if you know what you're doing!
+ +- +
ignorewarnings
+ = "boolean" + (default = false)- Print warnings about unresolved references, but continue processing + anyhow. Only use this option if you know what you're doing!
+ +- +
printconfiguration
+ = "boolean or filename" + (default = false)- Write out the entire configuration in traditional ProGuard style, to the + standard output or to the given file. Useful to replace unreadable + XML configurations.
+ +- +
dump
+ = "boolean or filename" + (default = false)- Write out the internal structure of the processed class files, to the + standard output or to the given file.
+ +- +
<injar
+ class_path +/>
- Specifies the program jars (or wars, ears, zips, or directories).
+ +- +
<outjar
+ class_path +/>
- Specifies the names of the output jars (or wars, ears, zips, or + directories).
+ +- +
<libraryjar
+ class_path +/>
- Specifies the library jars (or wars, ears, zips, or directories).
+ +- +
<keepdirectory name =
"directory_name" +/>
+<keepdirectories filter =
"directory_filter" +/>
- Keep the specified directories in the output jars (or wars, ears, zips, or + directories).
+ +- +
<keep
+ modifiers + class_specification +>
+ class_member_specifications +</keep>
- Preserve the specified classes and class members.
+ +- +
<keepclassmembers
+ modifiers + class_specification +>
+ class_member_specifications +</keepclassmembers>
- Preserve the specified class members, if their classes are preserved as + well.
+ +- +
<keepclasseswithmembers
+ modifiers + class_specification +>
+ class_member_specifications +</keepclasseswithmembers>
- Preserve the specified classes and class members, if all of the + specified class members are present.
+ +- +
<keepnames
+ class_specification +>
+ class_member_specifications +</keepnames>
- Preserve the names of the specified classes and class members (if + they aren't removed in the shrinking step).
+ +- +
<keepclassmembernames
+ class_specification +>
+ class_member_specifications +</keepclassmembernames>
- Preserve the names of the specified class members (if they aren't removed + in the shrinking step).
+ +- +
<keepclasseswithmembernames
+ class_specification +>
+ class_member_specifications +</keepclasseswithmembernames>
- Preserve the names of the specified classes and class members, if + all of the specified class members are present (after the shrinking + step).
+ +- +
<whyareyoukeeping
+ class_specification +>
+ class_member_specifications +</whyareyoukeeping>
- Print details on why the given classes and class members are being kept in + the shrinking step.
+ +- +
<assumenosideeffects
+ class_specification +>
+ class_member_specifications +</assumenosideeffects>
- Assume that the specified methods don't have any side effects, while + optimizing. Only use this option if you know what you're + doing!
+ +- +
<optimization name =
"optimization_name" +/>
+<optimizations filter =
""optimization_filter" +/>
- Perform only the specified optimizations.
+ +- +
<keeppackagename name =
"package_name" +/>
+<keeppackagenames filter =
"package_filter" +/>
- Keep the specified package names from being obfuscated. If no name is + given, all package names are preserved.
+ +- +
<keepattribute name =
"attribute_name" +/>
+<keepattributes filter =
"attribute_filter" +/>
- Preserve the specified optional Java bytecode attributes, with optional + wildcards. If no name is given, all attributes are preserved.
+ +- +
<adaptclassstrings filter =
"class_filter" +/>
- Adapt string constants in the specified classes, based on the obfuscated + names of any corresponding classes.
+ +- +
<adaptresourcefilenames filter =
"file_filter" +/>
- Rename the specified resource files, based on the obfuscated names of the + corresponding class files.
+ +- +
<adaptresourcefilecontents filter =
"file_filter" +/>
- Update the contents of the specified resource files, based on the + obfuscated names of the processed classes.
+ +- +
+<dontnote filter =
"class_filter" +/>
- Don't print notes about classes matching the specified class name + filter.
+ +- +
+<dontwarn filter =
"class_filter" +/>
- Don't print warnings about classes matching the specified class name + filter. Only use this option if you know what you're doing!
+ +- +
<configuration refid =
"ref_id" +/>
+<configuration file =
"name" +/>
- The first form includes the XML-style configuration specified in a +
+ +<proguardconfiguration>
task (or +<proguard>
task) with attributeid
= + "ref_id". Only the nested elements of this configuration are + considered, not the attributes. ++ The second form includes the ProGuard-style configuration from the specified + file. The element is actually a
fileset
element and supports + all of its attributes and nested elements, including multiple files. +Class Path Attributes and Nested Elements
+ +The jar elements arepath
elements, so they can have any of the +standardpath
attributes and nested elements. The most common +attributes are: + ++ +
+ +In addition, the jar elements can have ProGuard-style filter attributes: + +- +
path
= "path"- The names of the jars (or wars, ears, zips, or directories), separated by + the path separator.
+ +- +
location
= "name" (orfile
+ = "name", ordir
= "name", or +name
= "name")- Alternatively, the name of a single jar (or war, ear, zip, or + directory).
+ +- +
refid
= "ref_id"- Alternatively, a reference to the path or file set with the attribute +
+ +id
= "ref_id".+ +
+ +- +
filter
= + "file_filter"- An optional filter for all class file names and resource file names that + are encountered.
+ +- +
jarfilter
= + "file_filter"- An optional filter for all jar names that are encountered.
+ +- +
warfilter
= + "file_filter"- An optional filter for all war names that are encountered.
+ +- +
earfilter
= + "file_filter"- An optional filter for all ear names that are encountered.
+ +- +
zipfilter
= + "file_filter"- An optional filter for all zip names that are encountered.
+ +Keep Modifier Attributes
+ +The keep tags can have the following modifier attributes: + ++ +
+ +- +
allowshrinking
+ = "boolean" + (default = false)- Specifies whether the entry points specified in the keep tag may be + shrunk.
+ +- +
allowoptimization
+ = "boolean" + (default = false)- Specifies whether the entry points specified in the keep tag may be + optimized.
+ +- +
allowobfuscation
+ = "boolean" + (default = false)- Specifies whether the entry points specified in the keep tag may be + obfuscated.
+ +Class Specification Attributes and Nested Elements
+ +The keep tags can have the following class_specification attributes and +class_member_specifications nested elements: + ++ +
+ +- +
access
= "access_modifiers"- The optional access modifiers of the class. Any space-separated list of + "public", "final", and "abstract", with optional negators "!".
+ +- +
annotation
= "annotation_name"- The optional fully qualified name of an annotation of the class, with + optional wildcards.
+ +- +
type
= "type"- The optional type of the class: one of "class", "interface", or + "!interface".
+ +- +
name
= "class_name"- The optional fully qualified name of the class, with optional + wildcards.
+ +- +
extendsannotation
= "annotation_name"- The optional fully qualified name of an annotation of the the class that + the specified classes must extend, with optional wildcards.
+ +- +
extends
= "class_name"- The optional fully qualified name of the class the specified classes + must extend, with optional wildcards.
+ +- +
implements
= "class_name"- The optional fully qualified name of the class the specified classes + must implement, with optional wildcards.
+ +- +
<field
+ class_member_specification +/>
- Specifies a field.
+ +- +
<method
+ class_member_specification +/>
- Specifies a method.
+ +- +
<constructor
+ class_member_specification +/>
- Specifies a constructor.
+ +Class Member Specification Attributes
+ +The class member tags can have the following class_member_specification +attributes: + ++ +
+ +- +
access
= "access_modifiers"- The optional access modifiers of the class. Any space-separated list of + "public", "protected", "private", "static", etc., with optional negators + "!".
+ +- +
annotation
= "annotation_name"- The optional fully qualified name of an annotation of the class member, + with optional wildcards.
+ +- +
type
= "type"- The optional fully qualified type of the class member, with optional + wildcards. Not applicable for constructors, but required for methods for + which the
+ +parameters
attribute is specified.- +
name
= "name"- The optional name of the class member, with optional wildcards. Not + applicable for constructors.
+ +- +
parameters
= "parameters"- The optional comma-separated list of fully qualified method parameters, + with optional wildcards. Not applicable for fields, but required for + constructors, and for methods for which the
+ +type
attribute is + specified.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/attention.gif b/docs/manual/attention.gif new file mode 100644 index 0000000000000000000000000000000000000000..1a0c712d60e41120fa963b4cf988a54f21a69e27 GIT binary patch literal 896 zcmdVX{V&u30LSsqopT;<=dtCIxihsztX7AiWB8&?Y^hW8kcY+Q>6EG8aOdI<$>kwJ z=R{Yei;GK_eF>|uQVC6V&Q`Zk^Dyn0sQ!%Jd;bTo@JPbfFF6Q77$fjE3I$XuOiVzh z!^{j87O=7cg8?QJc6MN~;N}J|FC0G(A0PPpBOm}g9wH+V6$L&YadAjUKvEJ?Q<0X2 z^mJroATtwLS;)>tZY~4@6cj)xgh&Lj7*Z)@GSt+dsR;@N+S<_Gj-DR$_M)#3gM%PR z3=QG+YrJ`b@o`K};@vyU&SGv3^Yd6*g2900Wvs1XeH}(4wzjanjh!9*{*B#T?Ct$e zv$tpzOBBNMpTs{CnC%u73PmO28>M9uX?aEE&8l0~vfDMab@g`|8t*nWx7?GrD%$S1 zcRWx&6r$^qtV`8hrBe4)s-N~rHO~ghw9f~{8L%ICwkQPPHlx626FSD9I0!7tsdT4Bsomj;{0oJ9VPG+*W=mB!1s&nB0-tVp`iE zI5=AzO?}K EJYK+7bIRe$2Kjo`{_(sD4qQi&cFnzOaze zuUSdvQbo1QiR~kMip^YgHJj(0>SCOm3Z5b2W0Zndo5Nq~@&fZ2A?Tz95Ye%L22KuB z9jE!$IKl0%(nP(NEwbFN*2xm~u9K%ta@ + + + + + + ProGuard Examples + + + + +Examples
+ +Some typical useful configurations: ++
+ +You can find some sample configuration files in the- A typical application
+- A typical applet
+- A typical midlet
+- A typical Java Card applet
+- A typical xlet
+- A simple Android activity
+- A complete Android application
+- A typical library
+- All possible applications in the input jars
+- All possible applets in the input jars
+- All possible midlets in the input jars
+- All possible Java Card applets in the input jars
+- All possible xlets in the input jars
+- All possible servlets in the input jars
+- Scala applications with the Scala runtime
+- Processing native methods
+- Processing callback methods
+- Processing enumeration classes
+- Processing serializable classes
+- Processing bean classes
+- Processing annotations
+- Processing database drivers
+- Processing ComponentUI classes
+- Processing RMI code
+- Processing resource injection
+- Processing resource files
+- Processing manifest files
+- Producing useful obfuscated stack traces
+- Obfuscating package names
+- Removing logging code
+- Restructuring the output archives
+- Filtering the input and the output
+- Processing multiple applications at once
+- Incremental obfuscation
+- Preverifying class files for Java Micro Edition
+- Upgrading class files to Java 6
+- Finding dead code
+- Printing out the internal structure of class files
+- Using annotations to configure ProGuard
+examples
+directory of the ProGuard distribution. + +A typical application
+ +To shrink, optimize, and obfuscate a simple Java application, you typically +create a configuration file likemyconfig.pro
, which can be used +with ++bin/proguard @myconfig.pro +++The configuration file specifies the input, the output, and the entry points +of the application: +
+-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[]); +} +++Note the use of the
<java.home>
system property. ProGuard +automatically replaces it when parsing the file. ++The
-keep
option specifies the +entry point of the application that has to be preserved. +The access modifierspublic
andstatic
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. ++Note that all type names are fully specified: +
mypackage.MyMain
andjava.lang.String[]
. ++We're writing out an obfuscation mapping file with
-printmapping
, for +de-obfuscating any stack traces later on, or for incremental obfuscation of +extensions. ++We can further improve the results with a few additional options: +
+-optimizationpasses 3 +-overloadaggressively +-repackageclasses '' +-allowaccessmodification ++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 package names. ++In general, you might need a few additional options for processing native methods, callback methods, +enumerations, serializable +classes, bean classes, annotations, and resource +files. + +
A typical applet
+ +These options shrink, optimize, and obfuscate the applet +mypackage.MyApplet
: ++-injars in.jar +-outjars out.jar +-libraryjars <java.home>/lib/rt.jar + +-keep public class mypackage.MyApplet +++The typical applet methods will be preserved automatically, since +
mypackage.MyApplet
is an extension of theApplet
+class in the libraryrt.jar
. ++If applicable, you should add options for processing native +methods, callback methods, enumerations, serializable +classes, bean classes, annotations, and resource +files. + +
A typical midlet
+ +These options shrink, optimize, obfuscate, and preverify the midlet +mypackage.MyMIDlet
: ++-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 +++Note how we're now targeting the Java Micro Edition run-time environment of +
midpapi20.jar
andcldcapi11.jar
, instead of the Java +Standard Edition run-time environmentrt.jar
. You can target +other JME environments by picking the appropriate jars. ++The typical midlet methods will be preserved automatically, since +
mypackage.MyMIDlet
is an extension of theMIDlet
+class in the librarymidpapi20.jar
. ++The
-microedition
option +makes sure the class files are preverified for Java Micro Edition, producing +compactStackMap
attributes. It is no longer necessary to run an +external preverifier. ++Be careful if you do use the external
preverify
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-dontusemixedcaseclassnames
+option. ++If applicable, you should add options for processing native +methods and resource files. +
+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 typical Java Card applet
+ +These options shrink, optimize, and obfuscate the Java Card applet +mypackage.MyApplet
: ++-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 +++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 typical xlet
+ +These options shrink, optimize, and obfuscate the xlet +mypackage.MyXlet
: ++-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 +++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 simple Android activity
+ +These options shrink, optimize, and obfuscate the single Android +activitymypackage.MyActivity
: ++-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 +++We're targeting the Android run-time and keeping the activity as an entry +point. +
+Preverification is irrelevant for the dex compiler and the Dalvik VM, so we +can switch it off with the +
-dontpreverify
option. ++The
-optimizations
option +disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle. +Note that the Dalvik VM also can't +handle aggressive overloading +(of static fields). ++If applicable, you should add options for processing native +methods, callback methods, +enumerations, +annotations, and +resource files. + +
A complete Android application
+ + +The Ant and Eclipse build processes of the Android SDK already integrate +ProGuard by default, with all the proper settings. You only need to enable +ProGuard (for release builds), by uncommenting the line +"proguard.config=.....
" in the file +project.properties
(created or updated by Android SDK revision 17 +or higher). Notes: ++
+- In case of problems, you may want to check if the configuration files that + are listed on this line (
+proguard-project.txt
,...) contain + the necessary settings for your application.- Android SDK revision 20 and higher have a different configuration file for + enabling optimization: +
+${sdk.dir}/tools/proguard/proguard-android-optimize.txt
+ instead of the default +${sdk.dir}/tools/proguard/proguard-android.txt
.- The build processes are already setting the necessary program jars, + library jars, and output jars for you — don't specify them again.
+- If you get warnings about missing referenced classes: it's all too common + that libraries refer to missing classes. + See "Warning: can't find + referenced class" in the Troubleshooting section.
++For more information, you can consult the official Developer +Guide in the Android SDK. +
+If you're constructing a build process from scratch: these options shrink, +optimize, and obfuscate all public activities, services, broadcast receivers, +and content providers from the compiled classes and external libraries: +
+-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 android.os.Parcelable$Creator CREATOR; +} + +-keepclassmembers class **.R$* { + public static <fields>; +} +++Most importantly, we're keeping all fundamental classes that may be referenced +by the
AndroidManifest.xml
file of the application. If your +manifest file contains other classes and methods, you may have to specify +those as well. ++We're keeping annotations, since they might be used by custom +
RemoteViews
. ++We're keeping any custom
View
extensions and other classes with +typical constructors, since they might be referenced from XML layout files. ++We're also keeping possible
onClick
handlers in +customContext
extensions, since they might be referenced from +XML layout files. ++We're also keeping the required static fields in
Parcelable
+implementations, since they are accessed by introspection. ++Finally, we're keeping the static fields of referenced inner classes of +auto-generated
R
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). ++If you're using additional Google APIs, you'll have to specify +those as well, for instance: +
+-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar +++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
ILicensingService
interface for the library to work: ++-keep public interface com.android.vending.licensing.ILicensingService +++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: +
+-dontwarn android.support.** +++If applicable, you should add options for processing native +methods, callback methods, +enumerations, +and resource files. You may also want to add +options for producing useful stack traces and +to remove logging. You can find a complete sample +configuration in
examples/android.pro
in the ProGuard +distribution. + +A typical library
+ +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. ++-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 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 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(); +} +++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
-keep
options. ++The
-keepclassmembernames
+option for theclass$
methods is not strictly necessary. These +methods are inserted by thejavac
compiler and the +jikes
compiler respectively, in JDK 1.2 and older, to implement +the.class
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. ++The "Exceptions" attribute has to be preserved, so the compiler knows which +exceptions methods may throw. +
+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
javac
compiler would be unable to find the inner +classes otherwise. ++The "Signature" attribute is required to be able to access generic types when +compiling in JDK 5.0 and higher. +
+The
-keepparameternames
+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. ++Finally, we're keeping the "Deprecated" attribute and the attributes for +producing useful stack traces. +
+We've also added some options for for processing native +methods, enumerations, serializable classes, and annotations, which are all discussed in their +respective examples. + +
All possible applications in the input jars
+ +These options shrink, optimize, and obfuscate all public applications in +in.jar
: ++-injars in.jar +-outjars out.jar +-libraryjars <java.home>/lib/rt.jar +-printseeds + +-keepclasseswithmembers public class * { + public static void main(java.lang.String[]); +} +++Note the use of
-keepclasseswithmembers
. +We don't want to preserve all classes, just all classes that have main +methods, and those methods. ++The
-printseeds
option prints +out which classes exactly will be preserved, so we know for sure we're getting +what we want. ++If applicable, you should add options for processing native +methods, callback methods, enumerations, serializable +classes, bean classes, annotations, and resource +files. + +
All possible applets in the input jars
+ +These options shrink, optimize, and obfuscate all public applets in +in.jar
: ++-injars in.jar +-outjars out.jar +-libraryjars <java.home>/lib/rt.jar +-printseeds + +-keep public class * extends java.applet.Applet +++We're simply keeping all classes that extend the
Applet
class. ++Again, the
-printseeds
option +prints out which applets exactly will be preserved. ++If applicable, you should add options for processing native +methods, callback methods, enumerations, serializable +classes, bean classes, annotations, and resource +files. + +
All possible midlets in the input jars
+ +These options shrink, optimize, obfuscate, and preverify all public midlets in +in.jar
: ++-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 +++We're simply keeping all classes that extend the
MIDlet
class. ++The
-microedition
option +makes sure the class files are preverified for Java Micro Edition, producing +compactStackMap
attributes. It is no longer necessary to run an +external preverifier. ++Be careful if you do use the external
preverify
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-dontusemixedcaseclassnames
+option. ++The
-printseeds
option prints +out which midlets exactly will be preserved. ++If applicable, you should add options for processing native +methods and resource files. +
+Note that you will still have to adapt the midlet jar size in the +corresponding jad file; ProGuard doesn't do that for you. + +
All possible Java Card applets in the input jars
+ +These options shrink, optimize, and obfuscate all public Java Card applets in +in.jar
: ++-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 +++We're simply keeping all classes that implement the
Applet
+interface. ++The
-printseeds
option prints +out which applets exactly will be preserved. + +All possible xlets in the input jars
+ +These options shrink, optimize, and obfuscate all public xlets in +in.jar
: ++-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 +++We're simply keeping all classes that implement the
Xlet
interface. ++The
-printseeds
option prints +out which xlets exactly will be preserved. + +All possible servlets in the input jars
+ +These options shrink, optimize, and obfuscate all public servlets in +in.jar
: ++-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 +++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. +
+We're then keeping all classes that implement the
Servlet
+interface. We're using theimplements
keyword because it looks +more familiar in this context, but it is equivalent toextends
, +as far as ProGuard is concerned. ++The
-printseeds
option prints +out which servlets exactly will be preserved. ++If applicable, you should add options for processing native +methods, callback methods, enumerations, serializable +classes, bean classes, annotations, and resource +files. + +
Scala applications with the Scala runtime
+ +These options shrink, optimize, and obfuscate all public Scala applications in +in.jar
: ++-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; +} +++The configuration is essentially the same as +for processing applications, 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). +
+The
-dontwarn
option tells +ProGuard not to complain about some artefacts in the Scala runtime, the way it +is compiled by thescalac
compiler (at least in Scala 2.9.1 and +older). Note that this option should always be used with care. ++The additional
-keep
+options make sure that some classes and some fields that are accessed by means +of introspection are not removed or renamed. ++If applicable, you should add options for processing native +methods, callback methods, enumerations, serializable +classes, bean classes, annotations, and resource +files. +
Processing native methods
+ +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: ++-keepclasseswithmembernames class * { + native <methods>; +} +++Note the use of
-keepclasseswithmembernames
. +We don't want to preserve all classes or all native methods; we just want to +keep the relevant names from being obfuscated. ++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. Callback methods are discussed below as a typical example. + +
Processing callback methods
+ +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-keep
options, something like +the following option will keep the callback class and method: ++-keep class mypackage.MyCallbackClass { + void myCallbackMethod(java.lang.String); +} +++This will preserve the given class and method from being removed or renamed. + +
Processing enumeration classes
+ +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: ++-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} ++ +Processing serializable classes
+ +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: ++ +
+- 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: + +
+ ++-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(); +} +++ + The
-keepclassmembers
+ option makes sure that any serialization methods are kept. By using this + option instead of the basic-keep
option, we're not + forcing preservation of all serializable classes, just preservation + of the listed members of classes that are actually used.- 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
+ +serialVersionUID
fields. The following options should + then be sufficient to ensure compatibility over time: + ++-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(); +} +++ + The
serialVersionUID
andserialPersistentFields
+ lines makes sure those fields are preserved, if they are present. + The<fields>
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.- Occasionally, the serialized data have to remain compatible, but the + classes involved lack
+ +serialVersionUID
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 Stream + Unique Identifiers of Sun's Java + Object Serialization Specification. The following directives should at + least partially ensure compatibility with the original classes: + ++-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(); +} +++ + 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 "
-keep + interface MyInterface
"), since these names are also used when + computing the UID. A fast but sub-optimal alternative would be simply + keeping all interfaces with "-keep interface *
".+ +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
Serialization
interface, yet only a small number may actually +ever be serialized. Knowing your application and tuning the configuration +often produces more compact results. + +Processing bean classes
+ +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: ++-keep public class mypackage.MyBean { + public void setMyProperty(int); + public int getMyProperty(); +} + +-keep public class mypackage.MyBeanEditor +++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
mybeans
: ++-keep class mybeans.** { + void set*(***); + void set*(int, ***); + + boolean is*(); + boolean is*(int); + + *** get*(); + *** get*(int); +} +++The '
***
' wildcard matches any type (primitive or non-primitive, +array or non-array). The methods with the 'int
' arguments matches +properties that are lists. + +Processing annotations
+ +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: ++-keepattributes *Annotation* +++For brevity, we're specifying a wildcarded attribute name, which will match +
RuntimeVisibleAnnotations
, +RuntimeInvisibleAnnotations
, +RuntimeVisibleParameterAnnotations
, +RuntimeInvisibleParameterAnnotations
, and +AnnotationDefault
. 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). ++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: +
+-keepattributes EnclosingMethod ++ +Processing database drivers
+ +Database drivers are implementations of theDriver
interface. +Since they are often created dynamically, you may want to preserve any +implementations that you are processing as entry points: ++-keep class * implements java.sql.Driver +++This option also gets rid of the note that ProGuard prints out about +
(java.sql.Driver)Class.forName
constructs, if you are +instantiating a driver in your code (without necessarily implementing any +drivers yourself). + +Processing ComponentUI classes
+ +Swing UI look and feels are implemented as extensions of the +ComponentUI
class. For some reason, these have to contain a +static methodcreateUI
, which the Swing API invokes using +introspection. You should therefore always preserve the method as an entry +point, for instance like this: ++-keep class * extends javax.swing.plaf.ComponentUI { + public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent); +} +++This option also keeps the classes themselves. + +
Processing RMI code
+ +Reportedly, the easiest way to handle RMI code is to process the code with +ProGuard first and then invoke thermic
tool. If that is not +possible, you may want to try something like this: ++-keepattributes Exceptions + +-keep interface * extends java.rmi.Remote { + <methods>; +} + +-keep class * implements java.rmi.Remote { + <init>(java.rmi.activation.ActivationID, java.rmi.MarshalledObject); +} +++The first
-keep
option keeps all your Remote interfaces and their +methods. The second one keeps all the implementations, along with their +particular RMI constructors, if any. ++The
Exceptions
attribute has to be kept too, because the RMI +handling code performs introspection to check whether the method signatures +are compatible. + +Processing resource injection
+ +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@Resource
. 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: ++-keepclassmembers class * { + @javax.annotation.Resource *; +} +++The Spring framework has another similar annotation
@Autowired
: ++-keepclassmembers class * { + @org.springframework.beans.factory.annotation.Autowired *; +} ++ +Processing resource files
+ +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: ++-adaptresourcefilenames **.properties,**.gif,**.jpg +-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF +++The -adaptresourcefilenames +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 -adaptresourcefilecontents +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. + +
Processing manifest files
+ +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. ++If you're merging several input jars into a single output jar, you'll have to +pick one, typically by specifying filters: +
+-injars in1.jar +-injars in2.jar(!META-INF/MANIFEST.MF) +-injars in3.jar(!META-INF/MANIFEST.MF) +-outjars out.jar +++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. + +
Producing useful obfuscated stack traces
+ +These options let obfuscated applications or libraries produce stack traces +that can still be deciphered later on: ++-printmapping out.map + +-renamesourcefileattribute SourceFile +-keepattributes SourceFile,LineNumberTable +++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. +
+We're also keeping the line number tables of all methods. +
+Whenever both of these attributes are present, the Java run-time environment +will include line number information when printing out exception stack traces. +
+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 +
out.map
. The information can then be used by the ReTrace tool to restore the original stack trace. + +Obfuscating package names
+ +Package names can be obfuscated in various ways, with increasing levels of +obfuscation and compactness. For example, consider the following classes: ++mycompany.myapplication.MyMain +mycompany.myapplication.Foo +mycompany.myapplication.Bar +mycompany.myapplication.extra.FirstExtra +mycompany.myapplication.extra.SecondExtra +mycompany.util.FirstUtil +mycompany.util.SecondUtil +++Let's assume the class name
mycompany.myapplication.MyMain
is the +main application class that is kept by the configuration. All other class names +can be obfuscated. ++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: +
+mycompany.myapplication.MyMain +mycompany.myapplication.a +mycompany.myapplication.b +mycompany.myapplication.a.a +mycompany.myapplication.a.b +mycompany.a.a +mycompany.a.b +++The
-flattenpackagehierarchy
+option obfuscates the package names further, by flattening the package +hierarchy of obfuscated packages: ++-flattenpackagehierarchy 'myobfuscated' +++The obfuscated class names then look as follows: +
+mycompany.myapplication.MyMain +mycompany.myapplication.a +mycompany.myapplication.b +myobfuscated.a.a +myobfuscated.a.b +myobfuscated.b.a +myobfuscated.b.b +++Alternatively, the
-repackageclasses
option +obfuscates the entire packaging, by combining obfuscated classes into a single +package: ++-repackageclasses 'myobfuscated' ++The obfuscated class names then look as follows: ++mycompany.myapplication.MyMain +mycompany.myapplication.a +mycompany.myapplication.b +myobfuscated.a +myobfuscated.b +myobfuscated.c +myobfuscated.d +++Additionally specifying the
-allowaccessmodification
+option allows access permissions of classes and class members to +be broadened, opening up the opportunity to repackage all obfuscated classes: ++-repackageclasses 'myobfuscated' +-allowaccessmodification ++The obfuscated class names then look as follows: ++mycompany.myapplication.MyMain +myobfuscated.a +myobfuscated.b +myobfuscated.c +myobfuscated.d +myobfuscated.e +myobfuscated.f +++The specified target package can always be the root package. For instance: +
+-repackageclasses '' +-allowaccessmodification ++The obfuscated class names are then the shortest possible names: ++mycompany.myapplication.MyMain +a +b +c +d +e +f +++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 resource files that have to be adapted. + +
Removing logging code
+ +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). ++For example, this configuration removes invocations of the Android logging +methods: +
+-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(...); +} +++The wildcards are a shortcut to match all versions of the methods. +
+Note that you generally can't remove logging code that uses +
System.out.println
, since you would be removing all invocations +ofjava.io.PrintStream#println
, which could break your +application. You can work around it by creating your own logging methods and +let ProGuard remove those. + +Restructuring the output archives
+ +In simple applications, all output classes and resources files are merged into +a single jar. For example: ++-injars classes +-injars in1.jar +-injars in2.jar +-injars in3.jar +-outjars out.jar +++This configuration merges the processed versions of the files in the +
classes
directory and the three jars into a single output jar +out.jar
. ++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: +
+-injars in1.jar +-injars in2.jar +-injars in3.jar +-outjars out +++The input jars will then be reconstructed in the directory
out
, +with their original names. ++You can also combine archives into higher level archives. For example: +
+-injars in1.jar +-injars in2.jar +-injars in3.jar +-outjars out.war +++The other way around, you can flatten the archives inside higher level +archives into simple archives: +
+-injars in.war +-outjars out.jar +++This configuration puts the processed contents of all jars inside +
in.war
(plus any other contents ofin.war
) into +out.jar
. ++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 +
-injars
and-outjars
options. For example: ++-injars base_in1.jar +-injars base_in2.jar +-injars base_in3.jar +-outjars base_out.jar + +-injars extra_in.jar +-outjars extra_out.jar +++This configuration puts the processed results of all
base_in*.jar
+jars intobase_out.jar
, and the processed results of the +extra_in.jar
intoextra_out.jar
. Note that only the +order of the options matters; the additional whitespace is just for clarity. ++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. + +
Filtering the input and the output
+ +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: ++-injars in.jar(!images/**) +-outjars out.jar +++This configuration removes any files in the
images
directory and +its subdirectories. ++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: +
+-injars in1.jar +-injars in2.jar(!META-INF/MANIFEST.MF) +-injars in3.jar(!META-INF/MANIFEST.MF) +-outjars out.jar +++Another useful application is speeding up the processing by ProGuard, by +disregarding a large number of irrelevant classes in the runtime library jar: +
+-libraryjars <java.home>/lib/rt.jar(java/**,javax/**) +++The filter makes ProGuard disregard
com.sun.**
classes, for +instance , which don't affect the processing of ordinary applications. ++It is also possible to filter the jars (and/or wars, ears, zips) themselves, +based on their names. For example: +
+-injars in(**/acme_*.jar;) +-outjars out.jar +++Note the semi-colon in the filter; the filter in front of it applies to jar +names. In this case, only
acme_*.jar
jars are read from the +directoryin
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. ++On the other hand, you can also filter the output, in order to control what +content goes where. For example: +
+-injars in.jar +-outjars code_out.jar(**.class) +-outjars resources_out.jar +++This configuration splits the processed output, sending
**.class
+files tocode_out.jar
, and all remaining files to +resources_out.jar
. ++Again, the filtering can be arbitrarily complex, especially when combined with +grouping input and output. + +
Processing multiple applications at once
+ +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. ++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: +
+-injars application1.jar +-injars application2.jar +-injars application3.jar +-outjars processed_applications +++After processing, the directory
processed_applications
will +contain processed versions of application jars, with their original names. + +Incremental obfuscation
+ +After having processed an application, e.g. +ProGuard itself, you can still incrementally add other pieces of code that +depend on it, e.g. the ProGuard GUI: ++-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[]); +} +++We're reading both unprocessed jars as input. Their processed contents will go +to the respective output jars. The
-applymapping
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. ++The added code in this example is straightforward; it doesn't affect the +original code. The
proguard_out.jar
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-useuniqueclassmembernames
, +-dontshrink
, and-dontoptimize
in the +original processing step. 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: ++-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[]); +} ++ +Preverifying class files for Java Micro Edition
+ +Even if you're not interested in shrinking, optimizing, and obfuscating your +midlets, as shown in the midlets example, 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. ++-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 +++We're not processing the input, just making sure the class files are +preverified by targeting them at Java Micro Edition with the
-microedition
option. Note +that we don't need any-keep
options to specify entry points; all +class files are simply preverified. + +Upgrading class files to Java 6
+ +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. ++-injars in.jar +-outjars out.jar +-libraryjars <java.home>/lib/rt.jar + +-dontshrink +-dontoptimize +-dontobfuscate + +-target 1.6 +++We're not processing the input, just retargeting the class files with the
-target
option. They will +automatically be preverified for Java 6 as a result. Note that we don't need +any-keep
options to specify entry points; all class files are +simply updated and preverified. + +Finding dead code
+ +These options list unused classes, fields, and methods in the application +mypackage.MyApplication
: ++-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[]); +} +++We're not specifying an output jar, just printing out some results. We're +saving some processing time by skipping the other processing steps. +
+The java compiler inlines primitive constants and String constants +(
static final
fields). ProGuard would therefore list such fields +as not being used in the class files that it analyzes, even if they are +used in the source files. We can add a-keepclassmembers
option +that keeps those fields a priori, in order to avoid having them listed: ++-keepclassmembers class * { + static final % *; + static final java.lang.String *; +} ++ +Printing out the internal structure of class files
+ +These options print out the internal structure of all class files in the input +jar: ++-injars in.jar + +-dontshrink +-dontoptimize +-dontobfuscate +-dontpreverify + +-dump +++Note how we don't need to specify the Java run-time jar, because we're not +processing the input jar at all. + +
Using annotations to configure ProGuard
+ +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. ++You can find a set of such predefined annotations in the directory +
examples/annotations/lib
in the ProGuard distribution. +The annotation classes are defined inannotations.jar
. The +corresponding ProGuard configuration (or meta-configuration, if you prefer) +is specified inannotations.pro
. With these files, you can start +annotating your code. For instance, a java source file +Application.java
can be annotated as follows: ++@KeepApplication +public class Application { + .... +} +++The ProGuard configuration file for the application can then be simplified by +leveraging off these annotations: +
+-injars in.jar +-outjars out.jar +-libraryjars <java.home>/lib/rt.jar + +-include lib/annotations.pro +++The annotations are effectively replacing the application-dependent +
-keep
options. You may still wish to add traditional +-keep
options for processing native +methods, enumerations, serializable classes, and annotations. ++The directory
examples/annotations
contains more examples that +illustrate some of the possibilities. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/gradle.html b/docs/manual/gradle.html new file mode 100644 index 000000000..ef7280d36 --- /dev/null +++ b/docs/manual/gradle.html @@ -0,0 +1,545 @@ + + + + + + +Gradle Task + + + + +Gradle Task
+ +ProGuard can be run as a task in the Java-based build tool Gradle +(version 1.3 or higher). ++ +Before you can use the
proguard
task, you have to make sure +Gradle can find it in its class path at build time. One way is to add the +following line to yourbuild.gradle
file: ++ +
+buildscript { + repositories { + flatDir dirs: '/usr/local/java/proguard/lib' + } + dependencies { + classpath ':proguard' + } +} +++ +Please make sure the class path is set correctly for your system. +
+ +You can then define a task: +
+
+task myProguardTask(type: proguard.gradle.ProGuardTask) { + ..... +} +++ +The embedded configuration is much like a standard ProGuard configuration. +Notable similarities and differences: +
+
+- Like in ProGuard-style configurations, we're using all lower-case names + for the settings.
+- The options don't have a dash as prefix.
+- Arguments typically have quotes.
+- Some settings are specified as named arguments.
++You can find some sample build files in the
examples/gradle
+directory of the ProGuard distribution. ++If you prefer a more verbose configuration derived from the Ant task, you can +import the Ant task as a Gradle task. + +
Settings
+ +The ProGuard task supports the following settings in its closure: + ++ +
+ +- +
configuration
+ file- Read and merge options from the given ProGuard-style configuration + file.
+ +- +
injars
+ class_path- Specifies the program jars (or wars, ears, zips, or directories).
+ +- +
outjars
+ class_path- Specifies the names of the output jars (or wars, ears, zips, or + directories).
+ +- +
libraryjars
+ class_path- Specifies the library jars (or wars, ears, zips, or directories).
+ +- +
skipnonpubliclibraryclasses
- Ignore non-public library classes.
+ +- +
dontskipnonpubliclibraryclassmembers
- Don't ignore package visible library class members.
+ +- +
keepdirectories
+ ['directory_filter']- Keep the specified directories in the output jars (or wars, ears, zips, + or directories).
+ +- +
target
+ 'version'- Set the given version number in the processed classes.
+ +- +
forceprocessing
- Process the input, even if the output seems up to date.
+ +- +
keep
+ [modifier,...] + class_specification- Preserve the specified classes and class members.
+ +- +
keepclassmembers
+ [modifier,...] + class_specification- Preserve the specified class members, if their classes are preserved as + well.
+ +- +
keepclasseswithmembers
+ [modifier,...] + class_specification- Preserve the specified classes and class members, if all of the + specified class members are present.
+ +- +
keepnames
+ class_specification- Preserve the names of the specified classes and class members (if + they aren't removed in the shrinking step).
+ +- +
keepclassmembernames
+ class_specification- Preserve the names of the specified class members (if they aren't removed + in the shrinking step).
+ +- +
keepclasseswithmembernames
+ class_specification- Preserve the names of the specified classes and class members, if + all of the specified class members are present (after the shrinking + step).
+ +- +
printseeds
+ [file]- List classes and class members matched by the various
+ +keep
+ commands, to the standard output or to the given file.- +
dontshrink
- Don't shrink the input class files.
+ +- +
printusage
+ [file]- List dead code of the input class files, to the standard output or to the + given file.
+ +- +
whyareyoukeeping
+ class_specification- Print details on why the given classes and class members are being kept in + the shrinking step.
+ +- +
dontoptimize
- Don't optimize the input class files.
+ +- +
optimizations
'optimization_filter'- Perform only the specified optimizations.
+ +- +
optimizationpasses
+ n- The number of optimization passes to be performed.
+ +- +
assumenosideeffects
+ class_specification- Assume that the specified methods don't have any side effects, while + optimizing. Only use this option if you know what you're + doing!
+ +- +
allowaccessmodification
- Allow the access modifiers of classes and class members to be modified, + while optimizing.
+ +- +
mergeinterfacesaggressively
- Allow any interfaces to be merged, while optimizing.
+ +- +
dontobfuscate
- Don't obfuscate the input class files.
+ +- +
printmapping
+ [file]- Print the mapping from old names to new names for classes and class members + that have been renamed, to the standard output or to the given file.
+ +- +
applymapping
+ file- Reuse the given mapping, for incremental obfuscation.
+ +- +
obfuscationdictionary
+ file- Use the words in the given text file as obfuscated field names and method + names.
+ +- +
classobfuscationdictionary
+ file- Use the words in the given text file as obfuscated class names.
+ +- +
packageobfuscationdictionary
+ file- Use the words in the given text file as obfuscated package names.
+ +- +
overloadaggressively
- Apply aggressive overloading while obfuscating.
+ +- +
useuniqueclassmembernames
- Ensure uniform obfuscated class member names for subsequent incremental + obfuscation.
+ +- +
dontusemixedcaseclassnames
- Don't generate mixed-case class names while obfuscating.
+ +- +
keeppackagenames
['package_filter']- Keep the specified package names from being obfuscated. If no name is + given, all package names are preserved.
+ +- +
flattenpackagehierarchy
+ 'package_name'- Repackage all packages that are renamed into the single given parent + package.
+ +- +
repackageclasses
+ ['package_name']- Repackage all class files that are renamed into the single given + package.
+ +- +
keepattributes
['attribute_filter']- Preserve the specified optional Java bytecode attributes, with optional + wildcards. If no name is given, all attributes are preserved.
+ +- +
keepparameternames
- Keep the parameter names and types of methods that are kept.
+ +- +
renamesourcefileattribute
+ ['string']- Put the given constant string in the
+ +SourceFile
+ attributes.- +
adaptclassstrings
+ ['class_filter']- Adapt string constants in the specified classes, based on the obfuscated + names of any corresponding classes.
+ +- +
adaptresourcefilenames
+ ['file_filter']- Rename the specified resource files, based on the obfuscated names of the + corresponding class files.
+ +- +
adaptresourcefilecontents
+ ['file_filter']- Update the contents of the specified resource files, based on the + obfuscated names of the processed classes.
+ +- +
dontpreverify
- Don't preverify the processed class files if they are targeted at Java Micro + Edition or at Java 6 or higher.
+ +- +
microedition
- Target the processed class files at Java Micro Edition.
+ +- +
verbose
- Write out some more information during processing.
+ +- +
dontnote
'class_filter'- Don't print notes about classes matching the specified class name + filter.
+ +- +
dontwarn
'class_filter'- Don't print warnings about classes matching the specified class name + filter. Only use this option if you know what you're doing!
+ +- +
ignorewarnings
- Print warnings about unresolved references, but continue processing + anyhow. Only use this option if you know what you're doing!
+ +- +
printconfiguration
+ [file]- Write out the entire configuration in traditional ProGuard style, to the + standard output or to the given file. Useful to replace unreadable + XML configurations.
+ +- +
dump
+ [file]- Write out the internal structure of the processed class files, to the + standard output or to the given file.
+ +Class Paths
+ +Class paths are specified as Gradle file collections, which means they can be +specified as simple strings, withfiles(Object)
, etc. ++In addition, they can have ProGuard-style filters, specified as +comma-separated named arguments after the file: + +
+ +
+ +- +
filter:
+ 'file_filter'- An optional filter for all class file names and resource file names that + are encountered.
+ +- +
jarfilter:
+ 'file_filter'- An optional filter for all jar names that are encountered.
+ +- +
warfilter:
+ 'file_filter'- An optional filter for all war names that are encountered.
+ +- +
earfilter:
+ 'file_filter'- An optional filter for all ear names that are encountered.
+ +- +
zipfilter:
+ 'file_filter'- An optional filter for all zip names that are encountered.
+ +Files
+ +Files are specified as Gradle files, which means they can be specified +as simple strings, as File instances, withfile(Object)
, etc. ++In Gradle, file names (any strings really) in double quotes can contain +properties or code inside
${...}
. These are automatically +expanded. ++Like in ProGuard-style configurations, the names can also contain Java system +properties, delimited by angular brackets, '<' and '>'. +These properties are automatically replaced by their corresponding values. +
+For example,
<java.home>/lib/rt.jar
is automatically +expanded to something like/usr/local/java/jdk/jre/lib/rt.jar
. +Similarly,<user.home>
is expanded to the user's home +directory, and<user.dir>
is expanded to the current +working directory. + +Keep Modifiers
+ +The keep settings can have the following named arguments that modify their +behaviors: + ++ +
+ +Names arguments are comma-separated, as usual. + +- +
allowshrinking:
+ boolean + (default = false)- Specifies whether the entry points specified in the keep tag may be + shrunk.
+ +- +
allowoptimization:
+ boolean + (default = false)- Specifies whether the entry points specified in the keep tag may be + optimized.
+ +- +
allowobfuscation:
+ boolean + (default = false)- Specifies whether the entry points specified in the keep tag may be + obfuscated.
+ +Class Specifications
+ +A class specification is a template of classes and class members (fields and methods). There are two alternative ways to specify such a template: + ++
+- As a string containing a ProGuard-style class specification. This is the + most compact and most readable way. The specification looks like a Java + declaration of a class with fields and methods. For example: +
++keep 'public class mypackage.MyMainClass { \ + public static void main(java.lang.String[]); \ +}' +- As a Gradle-style setting: a method calls with named arguments and a + closure. This is more verbose, but it might be useful for programmatic + specifications. For example: +
++keep access: 'public', + name: 'mypackage.MyMainClass', { + method access: 'public static', + type: 'void', + name: 'main', + parameters: 'java.lang.String[]' +} ++ +The ProGuard-style class +specification is described on the traditional Usage page. +
+A Gradle-style class specification can have the following named arguments: + +
+ +
+ +The named arguments are optional. Without any arguments, there are no +constraints, so the settings match all classes. +- +
access:
'access_modifiers'- The optional access modifiers of the class. Any space-separated list of + "public", "final", and "abstract", with optional negators "!".
+ +- +
annotation:
'annotation_name'- The optional fully qualified name of an annotation of the class, with + optional wildcards.
+ +- +
type:
'type'- The optional type of the class: one of "class", "interface", or + "!interface".
+ +- +
name:
'class_name'- The optional fully qualified name of the class, with optional + wildcards.
+ +- +
extendsannotation:
'annotation_name'- The optional fully qualified name of an annotation of the the class that + the specified classes must extend, with optional wildcards.
+ +- +
'extends':
'class_name'- The optional fully qualified name of the class the specified classes + must extend, with optional wildcards.
+ +- +
'implements':
'class_name'- The optional fully qualified name of the class the specified classes + must implement, with optional wildcards.
+ ++ +
Gradle-style Class Member Specifications
+ +The closure of a Gradle-style class specification can specify class members +with these settings: + ++ +
+ +A class member setting can have the following named arguments to express +constraints: + +- +
field
field_constraints- Specifies a field.
+ +- +
method
method_constraints- Specifies a method.
+ +- +
constructor
constructor_constraints- Specifies a constructor.
+ ++ +
+ +The named arguments are optional. Without any arguments, there are no +constraints, so the settings match all constructors, fields, or methods. +- +
access:
'access_modifiers'- The optional access modifiers of the class. Any space-separated list of + "public", "protected", "private", "static", etc., with optional negators + "!".
+ +- +
'annotation':
'annotation_name'- The optional fully qualified name of an annotation of the class member, + with optional wildcards.
+ +- +
type:
'type'- The optional fully qualified type of the class member, with optional + wildcards. Not applicable for constructors, but required for methods for + which the
+ +parameters
argument is specified.- +
name:
'name'- The optional name of the class member, with optional wildcards. Not + applicable for constructors.
+ +- +
parameters:
'parameters'- The optional comma-separated list of fully qualified method parameters, + with optional wildcards. Not applicable for fields, but required for + constructors, and for methods for which the
+ +type
argument is + specified.+A class member setting doesn't have a closure. + +
Alternative: imported Ant task
+ +Instead of using the Gradle task, you could also integrate the Ant task in +your Gradle build file: ++
+ant.project.basedir = '../..' + +ant.taskdef(resource: 'proguard/ant/task.properties', + classpath: '/usr/local/java/proguard/lib/proguard.jar') +++ +Gradle automatically converts the elements and attributes to Groovy methods, +so converting the configuration is essentially mechanical. The one-on-one +mapping can be useful, but the resulting configuration is more verbose. For +instance: +
+task proguard << { + ant.proguard(printmapping: 'proguard.map', + overloadaggressively: 'on', + repackageclasses: '', + renamesourcefileattribute: 'SourceFile') { + + injar(file: 'application.jar') + injar(file: 'gui.jar', filter: '!META-INF/**') + + ..... + } +} +++ +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/gui.html b/docs/manual/gui.html new file mode 100644 index 000000000..6677aaf26 --- /dev/null +++ b/docs/manual/gui.html @@ -0,0 +1,481 @@ + + + + + + +ProGuard GUI + + + + +Graphical User Interface
+ +You can find the ProGuard GUI jar in thelib
directory of the +ProGuard distribution. To run the ProGuard graphical user interface, just type: ++
+Alternatively, thejava -jar proguardgui.jar [-nosplash]
[configuration_file] +bin
directory contains some short Linux and +Windows scripts containing this command. The GUI will pop up in a window. With +the-nosplash
option, you can switch off the short opening +animation. If you have specified a ProGuard configuration file, it will be +loaded. The GUI works like a wizard. You can edit the configuration and +execute ProGuard through a few tabs: ++ +
+
++ ProGuard +Optionally load an existing configuration file. + Input/Output +Specify the program jars and library jars. + Shrinking +Specify the shrinking options. + Obfuscation +Specify the obfuscation options. + Optimization +Specify the optimization options. + Information +Specify some options to get information. + Process +View and save the resulting configuration, and run ProGuard. + +In addition, there is a tab to execute ReTrace interactively: +
+ +
+
++ ReTrace +Set up and run ReTrace, to de-obfuscate stack traces. + +You can freely toggle between the tabs by means of the buttons on the +left-hand side of the window, or by means of the Previous and +Next buttons at the bottom of the tabs. Tool tips briefly explain the +purpose of the numerous options and text fields, although a basic +understanding of the shrinking/optimization/obfuscation/preverification +process is assumed. Please refer to the Introduction of this manual. +
+ +
The ProGuard Tab
+ +The ProGuard tab presents a welcome message and one important button at +the bottom: ++ +
+
++ Load configuration... +opens a file chooser to load an existing ProGuard configuration + file. + +If you don't want to load an existing configuration, you can just continue +creating a new configuration from scratch. +
+ +
The Input/Output Tab
+ +The Input/Output tab contains two lists, respectively to specify the +program jars (or wars, ears, zips, or directories), and the library jars (or +wars, ears, zips, or directories). + ++
+- The list of program jars contains input entries and output entries. Input + entries contain the class files and resource files to be processed. Output + entries specify the destinations to which the processed results will be + written. They are preceded by arrows, to distinguish them from input + entries. The results of each consecutive list of input entries will be + written to the subsequent consecutive list of output entries.
+ +- The library jars are not copied to the output jars; they contain class + files that are used by class files in the program jars and that are + necessary for correct processing. This list typically at least contains the + targeted Java runtime jar.
++ +Each of these lists can be edited by means of a couple of buttons on the +right-hand side: +
+ +
+
++ Add input... opens a file chooser to add an + input entry to the list of program jars. + Add output... opens a file chooser to add an + output entry to the list of program jars. + Add... +opens a file chooser to add an entry to the list of library + jars. + Edit... +opens a file chooser to edit the selected entry in the list. + Filter... +opens a text entry field to add or edit the filters of the selected + entries in the list. + Remove +removes the selected entries from the list. + Move up +moves the selected entries one position up the list. + Move down +moves the selected entries one position down the list. + Move to libraries +moves the selected entries in the list of program jars to the list of + library jars. + Move to program +moves the selected entries in the list of library jars to the list of + program jars. + +Filters allow to filter files based on their names. One can specify filters +for class file names and resource file names, for jar file names, for war file +names, for ear file names, and for zip file names. Multiple entries in the +program list only make sense when combined with filters; each output file is +written to the first entry with a matching filter. +
+ +Input entries that are currently not readable are colored red. +
+ +The order of the entries in each list may matter, as the first occurrence of +any duplicate entries gets precedence, just as in conventional class paths. +
+ +Corresponding configuration options: +
+
+- -injars
+- -outjars
+- -libraryjars
+- class_path
+- filters
++ +
The Shrinking Tab
+ +The Shrinking tab presents a number of options that affect the +shrinking step. The basic options are followed by a few lists of classes and +class members (fields and methods) that must be protected from shrinking (and +implicitly from obfuscation as well). ++ +The fixed lists contain predefined entries that are typically useful for many +applications. Each of these entries can be toggled by means of a check box. +The text field following each entry allows to constrain the applicable classes +by means of a comma-separated list of wildcarded, fully-qualified class +names. The default is "*", which means that all input classes of the +corresponding type are considered. +
+ +For example, checking the Applications entry and filling in +"myapplications.**" after it would mean: keep all classes that have main +methods in the "myapplications" package and all of its subpackages. +
+ +The variable list at the bottom allows to define additional entries +yourself. The list can be edited by means of a couple of buttons on the +right-hand side: +
+ +
+
++ Add... +opens a window to add a new entry to the list. + Edit... +opens a window to edit the selected entry in the list. + Remove +removes the selected entries from the list. + Move up +moves the selected entries one position up the list. + Move down +moves the selected entries one position down the list. + +The interface windows allow to specify classes, fields, and methods. They +contain text fields and check boxes to constrain these items. They have +Ok and Cancel buttons to apply or to cancel the operation. +
+ +For example, your application may be creating some classes dynamically using +
Class.forName
. You should then specify them here, so they are kept +by their original names. Press the Add... button to open the class +window. Fill out the fully-qualified class name in the Code text field, +and press the Ok button. Repeat this for all required classes. Wildcards +can be helpful to specify a large number of related classes in one go. If you +want to specify all implementations of a certain interface, fill out the +fully qualified interface name in the Extends/implements class instead. ++ +For more advanced settings, it is advisable to become familiar with ProGuard's +configuration options through the Usage section and +the Examples section. We'll suffice with a brief +overview of the three dialogs provided by the GUI. +
+ +The keep class dialog appears when adding or editing new special keep +entries. It has text fields and selections for specifying and constraining +classes and class members to keep. The Advanced options / Basic +options button at the bottom of the dialog allows to toggle showing the +advanced options. + +
+
+- The Comments text field allows to add optional comments to this + entry. The comments will identify the entry in the list and they will + appear as comments in the configuration file.
+ +- The Keep selection allows to specify whether you want to protect + the specified classes and their specified class members, or just the + specified class members from the specified classes, or the specified + classes and the specified class members, if the class members are present. + Note that class members will only be protected if they are explicitly + specified, even if only by means of a wildcard.
+ +- The Allow selection allows to specify whether you want to allow the + the specified classes and their specified class members to be shrunk, + optimized and/or obfuscated.
+ +- The Access selections allows to specify constraints on the class or + classes, based on their access modifiers.
+ +- The Annotation text field takes the fully-qualified name of an + annotation that is required for matching classes. The annotation name can + contain wildcards. This is an advanced option for defining keep + annotations.
+ +- The Class text field takes the fully-qualified name of the class or + classes. The class name can contain wildcards.
+ +- The Annotation text field takes the fully-qualified name of an + annotation that is required for the class or interface that the above + class must extend. The annotation name can contain wildcards. This is an + advanced option for defining keep annotations.
+ +- The Extends/implements class text field takes the fully-qualified + name of the class or interface that the above classes must extend.
+ +- The Class members list allows to specify a list of fields and + methods to keep. It can be edited by means of a list of buttons on the + right-hand side.
++ +The keep field dialog appears when adding or editing fields within the +above dialog. It has text fields and selections for specifying and +constraining fields to keep. Again, the Advanced options / Basic +options button at the bottom of the dialog allows to toggle showing the +advanced options. + +
+
+- The Access selections allows to specify constraints on the field or + fields, based on their access modifiers.
+ +- The Annotation text field takes the fully-qualified name of an + annotation that is required for matching fields. The annotation name can + contain wildcards. This is an advanced option for defining keep + annotations.
+ +- The Return type text field takes the fully-qualified type of the + field or fields. The type can contain wildcards.
+ +- The Name text field takes the name of the field or fields. The field + name can contain wildcards.
++ +Similarly, the keep method dialog appears when adding or editing +methods within the keep class dialog. It has text fields and selections for +specifying and constraining methods to keep. Again, the Advanced +options / Basic options button at the bottom of the dialog allows +to toggle showing the advanced options. + +
+
+- The Access selections allows to specify constraints on the method or + methods, based on their access modifiers.
+ +- The Annotation text field takes the fully-qualified name of an + annotation that is required for matching methods. The annotation name can + contain wildcards. This is an advanced option for defining keep + annotations.
+ +- The Return type text field takes the fully-qualified type of the method or methods. The type can contain wildcards.
+ +- The Name text field takes the name of the method or methods. The + method name can contain wildcards.
+ +- The Arguments text field takes the comma-separated list of + fully-qualified method arguments. Each of these arguments can contain + wildcards.
++ +Corresponding configuration options: +
+
+- -dontshrink
+- -printusage
+- -keep
+- -keepclassmembers
+- -keepclasseswithmembers
++ +
The Obfuscation Tab
+ +The Obfuscation tab presents a number of options that affect the +obfuscation step. The basic options are followed by a few lists of classes and +class members (fields and methods) that must be protected from obfuscation +(but not necessarily from shrinking). ++ +The lists are manipulated in the same way as in the Shrinking Tab. +
+ +Corresponding configuration options: +
+
+- -dontobfuscate
+- -printmapping
+- -applymapping
+- -obfuscationdictionary
+- -classobfuscationdictionary
+- -packageobfuscationdictionary
+- -overloadaggressively
+- -useuniqueclassmembernames
+- -dontusemixedcaseclassnames
+- -keeppackagenames
+- -flattenpackagehierarchy
+- -repackageclasses
+- -keepattributes
+- -keepparameternames
+- -renamesourcefileattribute
+- -adaptclassstrings
+- -adaptresourcefilenames
+- -adaptresourcefilecontents
+- -keepnames
+- -keepclassmembernames
+- -keepclasseswithmembernames
+- class_specification
++ +
The Optimization Tab
+ +The Optimization tab presents a number of options that affect the +optimization step. The basic options are followed by a few lists of class +method calls that can be removed if ProGuard can determine that their results +are not being used. ++ +The lists are manipulated in much the same way as in the Shrinking Tab. +
+ +Corresponding configuration options: +
+
+- -dontoptimize
+- -optimizations
+- -optimizationpasses
+- -allowaccessmodification
+- -mergeinterfacesaggressively
+- -assumenosideeffects
+- class_specification
++ +
The Information Tab
+ +The Information tab presents a number of options for preverification +and targeting, and for the information that ProGuard returns when processing +your code. The bottom list allows you to query ProGuard about why given +classes and class members are being kept in the shrinking step. ++ +Corresponding configuration options: +
+
+- -dontpreverify
+- -microedition
+- -target
+- -verbose
+- -dontnote
+- -dontwarn
+- -ignorewarnings
+- -skipnonpubliclibraryclasses
+- -dontskipnonpubliclibraryclasses
+- -dontskipnonpubliclibraryclassmembers
+- -keepdirectories
+- -forceprocessing
+- -printseeds
+- -printconfiguration
+- -dump
+- -whyareyoukeeping
++ +
The Process Tab
+ +The Process tab has an output console for displaying the configuration +and the messages while processing. There are three important buttons at the +bottom: ++ +
+
++ View configuration +displays the current ProGuard configuration in the console. + Save configuration... +opens a file chooser to save the current ProGuard + configuration. + Process! +executes ProGuard with the current configuration. + +
The ReTrace Tab
+ +The ReTrace tab has a panel with a few settings, an input text area for +the obfuscated stack trace, and an output console to view the de-obfuscated +stack trace: + ++
+ +There are two buttons at the bottom: +- The Verbose check box in the settings panel allows to toggle between + normal mode and verbose mode.
+ +- The Mapping file text field takes the name of the required mapping + file that ProGuard wrote while processing the original code. The file name + can be entered manually or by means of the Browse... button that + opens a file chooser.
+ +- The Obfuscated stack trace text area allows to enter the stack + trace, typically by copying and pasting it from elsewhere. Alternatively, + it can be loaded from a file by means of the load button below.
++ +
+
+ ++ Load stack trace... +opens a file chooser to load an obfuscated stack trace. + ReTrace! +executes ReTrace with the current settings.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/index.html b/docs/manual/index.html new file mode 100644 index 000000000..643a216ed --- /dev/null +++ b/docs/manual/index.html @@ -0,0 +1,52 @@ + + + + + + +ProGuard Manual + + + + +ProGuard
+ ++
+ +- Introduction
+- Usage
+- Limitations
+- Examples
+- Troubleshooting
+- Reference Card
+- Graphical User Interface
+- Ant Task
+- Gradle Task
+- JME Wireless Toolkit Integration
+ReTrace
+ ++
+ +- Introduction
+- Usage
+- Examples
+
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/introduction.html b/docs/manual/introduction.html new file mode 100644 index 000000000..3f181144c --- /dev/null +++ b/docs/manual/introduction.html @@ -0,0 +1,172 @@ + + + + + + +ProGuard Introduction + + + + +Introduction
+ +ProGuard is a Java class file shrinker, optimizer, obfuscator, and +preverifier. The shrinking step detects and removes unused classes, fields, +methods, and attributes. The optimization step analyzes and optimizes the +bytecode of the methods. The obfuscation step renames the remaining classes, +fields, and methods using short meaningless names. These first steps make the +code base smaller, more efficient, and harder to reverse-engineer. The final +preverification step adds preverification information to the classes, which is +required for Java Micro Edition and for Java 6 and higher. ++Each of these steps is optional. For instance, ProGuard can also be used to +just list dead code in an application, or to preverify class files for +efficient use in Java 6. +
+ +
+ +
++ + +Input jars ++ + + ++ Shrunk code ++ + + ++ Optim. code ++ Output jars ++ + +- shrink → +- optimize → +- obfuscate → +Obfusc. code +- preverify → ++ + +Library jars +------------------------------- (unchanged) -------------------------------→ +Library jars ++ +ProGuard first reads the input jars (or wars, ears, zips, or +directories). It then subsequently shrinks, optimizes, obfuscates, and +preverifies them. You can optionally let ProGuard perform multiple +optimization passes. ProGuard writes the processed results to one or +more output jars (or wars, ears, zips, or directories). The input may +contain resource files, whose names and contents can optionally be updated to +reflect the obfuscated class names. +
+ProGuard requires the library jars (or wars, ears, zips, or +directories) of the input jars to be specified. These are essentially the +libraries that you would need for compiling the code. ProGuard uses them to +reconstruct the class dependencies that are necessary for proper processing. +The library jars themselves always remain unchanged. You should still put them +in the class path of your final application. + +
Entry points
+ +In order to determine which code has to be preserved and which code can be +discarded or obfuscated, you have to specify one or more entry points to +your code. These entry points are typically classes with main methods, applets, +midlets, activities, etc. ++
+- In the shrinking step, ProGuard starts from these seeds and + recursively determines which classes and class members are used. All other + classes and class members are discarded.
+ +- In the optimization step, ProGuard further optimizes the code. + Among other optimizations, classes and methods that are not entry points + can be made private, static, or final, unused parameters can be removed, + and some methods may be inlined.
+ +- In the obfuscation step, ProGuard renames classes and class members + that are not entry points. In this entire process, keeping the entry + points ensures that they can still be accessed by their original names.
+ +- The preverification step is the only step that doesn't have to know + the entry points.
++The Usage section of this manual describes the +necessary
-keep
options and +the Examples section provides plenty of examples. + +Reflection
+ +Reflection and introspection present particular problems for any automatic +processing of code. In ProGuard, classes or class members in your code that +are created or invoked dynamically (that is, by name) have to be specified as +entry points too. For example,Class.forName()
constructs may +refer to any class at run-time. It is generally impossible to compute which +classes have to be preserved (with their original names), since the class +names might be read from a configuration file, for instance. You therefore +have to specify them in your ProGuard configuration, with the same +simple-keep
options. ++However, ProGuard will already detect and handle the following cases for you: + +
+
+ +The names of the classes and class members may of course be different, but the +constructs should be literally the same for ProGuard to recognize them. The +referenced classes and class members are preserved in the shrinking phase, and +the string arguments are properly updated in the obfuscation phase. +- +
Class.forName("SomeClass")
- +
SomeClass.class
- +
SomeClass.class.getField("someField")
- +
SomeClass.class.getDeclaredField("someField")
- +
SomeClass.class.getMethod("someMethod", new Class[] {})
- +
SomeClass.class.getMethod("someMethod", new Class[] { A.class })
- +
SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
- +
SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
- +
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
- +
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
- +
AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
- +
AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
- +
AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")
+Furthermore, ProGuard will offer some suggestions if keeping some classes or +class members appears necessary. For example, ProGuard will note constructs +like "
(SomeClass)Class.forName(variable).newInstance()
". These +might be an indication that the class or interfaceSomeClass
+and/or its implementations may need to be preserved. You can then adapt your +configuration accordingly. ++For proper results, you should at least be somewhat familiar with the code +that you are processing. Obfuscating code that performs a lot of reflection +may require trial and error, especially without the necessary information +about the internals of the code. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/limitations.html b/docs/manual/limitations.html new file mode 100644 index 000000000..6b6941097 --- /dev/null +++ b/docs/manual/limitations.html @@ -0,0 +1,69 @@ + + + + + + +ProGuard Limitations + + + + +Limitations
+ +When using ProGuard, you should be aware of a few technical issues, all of +which are easily avoided or resolved: ++
+ +
+ +- For best results, ProGuard's optimization algorithms assume that the + processed code never intentionally throws NullPointerExceptions or + ArrayIndexOutOfBoundsExceptions, or even OutOfMemoryErrors or + StackOverflowErrors, in order to achieve something useful. For instance, + it may remove a method call
+ +myObject.myMethod()
if that call + wouldn't have any effect. It ignores the possibility that +myObject
might be null, causing a NullPointerException. In + some way this is a good thing: optimized code may throw fewer exceptions. + Should this entire assumption be false, you'll have to switch off + optimization using the-dontoptimize
option.- ProGuard's optimization algorithms currently also assume that the + processed code never creates busy-waiting loops without at least + testing on a volatile field. Again, it may remove such loops. Should this + assumption be false, you'll have to switch off optimization using + the
+ +-dontoptimize
option.- If an input jar and a library jar contain classes in the same + package, the obfuscated output jar may contain class names that + overlap with class names in the library jar. This is most likely if the + library jar has been obfuscated before, as it will then probably contain + classes named 'a', 'b', etc. Packages should therefore never be split + across input jars and library jars.
+ +- When obfuscating, ProGuard writes out class files named + "
+ +a.class
", "b.class
", etc. If a package contains + a large number of classes, ProGuard may also write out + "aux.class
". Inconveniently, Windows refuses to create + files with this reserved name (among a few other names). It's generally + better to write the output to a jar, in order to avoid such problems.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/optimizations.html b/docs/manual/optimizations.html new file mode 100644 index 000000000..e4c96b6f7 --- /dev/null +++ b/docs/manual/optimizations.html @@ -0,0 +1,198 @@ + + + + + + +Optimizations + + + + +Optimizations
+ +The optimization step of ProGuard can be switched off with the +-dontoptimize
option. For +more fine-grained control over individual optimizations, experts can use the +-optimizations
option, +with a filter based on the optimization names listed below. The filter works +like any filter in ProGuard. ++ +The following wildcards are supported: + +
+
+ +An optimization that is preceded by an exclamation mark '!' is +excluded from further attempts to match with subsequent +optimization names in the filter. Make sure to specify filters correctly, +since they are not checked for potential typos. ++ + ?
matches any single character in an optimization name. + + *
matches any part of an optimization name. + +For example, +"
code/simplification/variable,code/simplification/arithmetic
" +only performs the two specified peephole optimizations. ++ +For example, "
!method/propagation/*
" performs all optimizations, +except the ones that propagate values between methods. ++ +For example, +"
!code/simplification/advanced,code/simplification/*
" only +performs all peephole optimizations. ++Some optimizations necessarily imply other optimizations. These are then +indicated. Note that the list is likely to change over time, as optimizations +are added and reorganized. +
+ +
+
+- +
class/marking/final
- Marks classes as final, whenever possible.
+ +- +
class/merging/vertical
- Merges classes vertically in the class hierarchy, whenever possible.
+ +- +
class/merging/horizontal
- Merges classes horizontally in the class hierarchy, whenever possible.
+ +- +
(⇒+code/removal/advanced
)field/removal/writeonly
- Removes write-only fields.
+ +- +
field/marking/private
- Marks fields as private, whenever possible.
+ +- +
(⇒+code/simplification/advanced
)field/propagation/value
- Propagates the values of fields across methods.
+ +- +
method/marking/private
- Marks methods as private, whenever possible (devirtualization).
+ +- +
(⇒+code/removal/advanced
)method/marking/static
- Marks methods as static, whenever possible (devirtualization).
+ +- +
method/marking/final
- Marks methods as final, whenever possible.
+ +- +
(⇒+code/removal/advanced
)method/removal/parameter
- Removes unused method parameters.
+ +- +
(⇒+code/simplification/advanced
)method/propagation/parameter
- Propagates the values of method parameters from method invocations to + the invoked methods.
+ +- +
(⇒+code/simplification/advanced
)method/propagation/returnvalue
- Propagates the values of method return values from methods to their + invocations.
+ +- +
method/inlining/short
- Inlines short methods.
+ +- +
method/inlining/unique
- Inlines methods that are only called once.
+ +- +
method/inlining/tailrecursion
- Simplifies tail recursion calls, whenever possible.
+ +- +
code/merging
- Merges identical blocks of code by modifying branch targets.
+ +- +
code/simplification/variable
- Performs peephole optimizations for variable loading and storing.
+ +- +
code/simplification/arithmetic
- Performs peephole optimizations for arithmetic instructions.
+ +- +
code/simplification/cast
- Performs peephole optimizations for casting operations.
+ +- +
code/simplification/field
- Performs peephole optimizations for field loading and storing.
+ +- +
(⇒+code/removal/simple
)code/simplification/branch
- Performs peephole optimizations for branch instructions.
+ +- +
code/simplification/string
- Performs peephole optimizations for constant strings.
+ +- +
(best used with+code/removal/advanced
)code/simplification/advanced
- Simplifies code based on control flow analysis and data flow + analysis.
+ +- +
(⇒+code/removal/exception
)code/removal/advanced
- Removes dead code based on control flow analysis and data flow + analysis.
+ +- +
(⇒+code/removal/exception
)code/removal/simple
- Removes dead code based on a simple control flow analysis.
+ +- +
code/removal/variable
- Removes unused variables from the local variable frame.
+ +- +
code/removal/exception
- Removes exceptions with empty try blocks.
+ +- +
code/allocation/variable
- Optimizes variable allocation on the local variable frame.
++ +ProGuard also provides some unofficial settings to control optimizations, that +may disappear in future versions. These are Java system properties, which +can be set as JVM arguments (with
-D.....)
: ++
+ +- +
maximum.inlined.code.length
(default = 8 bytes)- Specifies the maximum code length (expressed in bytes) of short methods + that are eligible to be inlined. Inlining methods that are too long may + unnecessarily inflate the code size.
+ +- +
maximum.resulting.code.length
(default = 8000 bytes + for JSE, 2000 bytes for JME)- Specifies the maximum resulting code length (expressed in bytes) allowed + when inlining methods. Many Java virtual machines do not apply just-in-time + compilation to methods that are too long, so it's important not to let them + grow too large.
+ +- +
optimize.conservatively
(default = unset)- Allows input code with ordinary instructions intentionally throwing +
+NullPointerException
, +ArrayIndexOutOfBoundsException
, or +ClassCastException
, without any other useful purposes. By + default, ProGuard may just discard such seemingly useless instructions, + resulting in better optimization of most common code.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/refcard.html b/docs/manual/refcard.html new file mode 100644 index 000000000..d9301bdb8 --- /dev/null +++ b/docs/manual/refcard.html @@ -0,0 +1,486 @@ + + + + + + +ProGuard Reference Card + + + + +ProGuard Reference Card
+ +Usage
+ +java -jar proguard.jar
options ... ++ Typically: +
+
java -jar proguard.jar @myconfig.pro
++ +
Options
+ ++ +
++ + ++ + @
filenameShort for ' +-include
filename'.+ + ++ + -include
+ filenameRead configuration options from the given file. ++ + ++ + -basedirectory
+ directorynameSpecifies the base directory for subsequent relative file names. ++ + ++ -injars
+ class_pathSpecifies the program jars (or wars, ears, zips, or directories). ++ + ++ -outjars
+ class_pathSpecifies the names of the output jars (or wars, ears, zips, or + directories). ++ + ++ -libraryjars
+ class_pathSpecifies the library jars (or wars, ears, zips, or directories). ++ + ++ -skipnonpubliclibraryclasses
Ignore non-public library classes. ++ + ++ -dontskipnonpubliclibraryclasses
Don't ignore non-public library classes (the default). ++ + ++ -dontskipnonpubliclibraryclassmembers
Don't ignore package visible library class members. ++ + ++ -keepdirectories
+ [directory_filter]Keep the specified directories in the output jars (or wars, ears, zips, or + directories). ++ + ++ -target
+ versionSet the given version number in the processed classes. ++ + ++ -forceprocessing
Process the input, even if the output seems up to date. ++ ++ -keep
+ [,modifier,...] + class_specificationPreserve the specified classes and class members. + ++ + ++ -keepclassmembers
+ [,modifier,...] + class_specificationPreserve the specified class members, if their classes are preserved as + well. ++ + ++ -keepclasseswithmembers
+ [,modifier,...] + class_specificationPreserve the specified classes and class members, if all of the + specified class members are present. ++ + ++ -keepnames
+ class_specificationPreserve the names of the specified classes and class members (if + they aren't removed in the shrinking step). ++ + ++ -keepclassmembernames
+ class_specificationPreserve the names of the specified class members (if they aren't removed + in the shrinking step). ++ + ++ -keepclasseswithmembernames
+ class_specificationPreserve the names of the specified classes and class members, if + all of the specified class members are present (after the shrinking + step). ++ + ++ -printseeds
+ [filename]List classes and class members matched by the various +-keep
+ options, to the standard output or to the given file.+ + ++ -dontshrink
Don't shrink the input class files. ++ + ++ -printusage
+ [filename]List dead code of the input class files, to the standard output or to the + given file. ++ + ++ -whyareyoukeeping
+ class_specificationPrint details on why the given classes and class members are being kept in + the shrinking step. ++ + ++ -dontoptimize
Don't optimize the input class files. ++ + ++ -optimizations
+ optimization_filterThe optimizations to be enabled and disabled. ++ + ++ -optimizationpasses
+ nThe number of optimization passes to be performed. ++ + ++ -assumenosideeffects
+ class_specificationAssume that the specified methods don't have any side effects, while + optimizing. ++ + ++ -allowaccessmodification
Allow the access modifiers of classes and class members to be modified, + while optimizing. ++ + ++ -mergeinterfacesaggressively
Allow any interfaces to be merged, while optimizing. ++ + ++ -dontobfuscate
Don't obfuscate the input class files. ++ + ++ -printmapping
+ [filename]Print the mapping from old names to new names for classes and class members + that have been renamed, to the standard output or to the given file. ++ + ++ -applymapping
+ filenameReuse the given mapping, for incremental obfuscation. ++ + ++ -obfuscationdictionary
+ filenameUse the words in the given text file as obfuscated field names and method names. ++ + ++ -classobfuscationdictionary
+ filenameUse the words in the given text file as obfuscated class names. ++ + ++ -packageobfuscationdictionary
+ filenameUse the words in the given text file as obfuscated package names. ++ + ++ -overloadaggressively
Apply aggressive overloading while obfuscating. ++ + ++ -useuniqueclassmembernames
Ensure uniform obfuscated class member names for subsequent incremental + obfuscation. + + ++ -dontusemixedcaseclassnames
Don't generate mixed-case class names while obfuscating. ++ + ++ -keeppackagenames
+ [package_filter]Keep the specified package names from being obfuscated. ++ + ++ -flattenpackagehierarchy
+ [package_name]Repackage all packages that are renamed into the single given parent + package. ++ + ++ -repackageclasses
+ [package_name]Repackage all class files that are renamed into the single given + package. ++ + ++ -keepattributes
+ [attribute_filter]Preserve the given optional attributes; typically + +Exceptions
,InnerClasses
, +Signature
,Deprecated
, +SourceFile
,SourceDir
, +LineNumberTable
, +LocalVariableTable
,LocalVariableTypeTable
, +Synthetic
,EnclosingMethod
, and +*Annotation*
.+ + ++ -keepparameternames
Keep the parameter names and types of methods that are kept. ++ + ++ -renamesourcefileattribute
+ [string]Put the given constant string in the +SourceFile
+ attributes.+ + ++ -adaptclassstrings
+ [class_filter]Adapt string constants in the specified classes, based on the obfuscated + names of any corresponding classes. ++ + ++ -adaptresourcefilenames
+ [file_filter]Rename the specified resource files, based on the obfuscated names of the + corresponding class files. ++ + ++ -adaptresourcefilecontents
+ [file_filter]Update the contents of the specified resource files, based on the + obfuscated names of the processed classes. ++ + ++ -dontpreverify
Don't preverify the processed class files. ++ + ++ -microedition
Target the processed class files at Java Micro Edition. ++ + ++ -verbose
Write out some more information during processing. ++ + ++ -dontnote
+ [class_filter]Don't print notes about potential mistakes or omissions in the + configuration. ++ + ++ -dontwarn
+ [class_filter]Don't warn about unresolved references at all. ++ + ++ -ignorewarnings
Print warnings about unresolved references, but continue processing + anyhow. ++ + ++ -printconfiguration
+ [filename]Write out the entire configuration in traditional ProGuard style, to the + standard output or to the given file. ++ + ++ -dump
+ [filename]Write out the internal structure of the processed class files, to the + standard output or to the given file. ++Notes: +
+ +
+- class_path is a list of jars, wars, ears, zips, and directories, + with optional filters, separated by path separators.
+- filename can contain Java system properties delimited by + '<' and '>'.
+- If filename contains special characters, the entire name + should be quoted with single or double quotes.
++ +
Overview of
+ +Keep
Options+ +
++ + +Keep +From being removed or renamed +From being renamed ++ + +Classes and class members ++ -keep
+ -keepnames
+ + +Class members only ++ -keepclassmembers
+ -keepclassmembernames
+ + +Classes and class members, if class members present ++ -keepclasseswithmembers
+ -keepclasseswithmembernames
+ +
Keep Option Modifiers
+ ++ +
++ + ++ allowshrinking
The entry points specified in the keep tag may be shrunk. ++ + ++ allowoptimization
The entry points specified in the keep tag may be optimized. ++ + ++ allowobfuscation
The entry points specified in the keep tag may be obfuscated. ++ +
Class Specifications
+ ++[@annotationtype] [[!]public|final|abstract ...] [!]interface|class classname + [extends|implements [@annotationtype] classname] +[{ + [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> | + (fieldtype fieldname); + [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> | + <init>(argumenttype,...) | + classname(argumenttype,...) | + (returntype methodname(argumenttype,...)); + [@annotationtype] [[!]public|private|protected|static ... ] *; + ... +}] +++Notes: +
+
+ +- Class names must always be fully qualified, i.e. including their package + names.
+- Types in classname, annotationtype, returntype, and + argumenttype can contain wildcards: '
+?
' for a + single character, '*
' for any number of characters + (but not the package separator), '**
' for any number + of (any) characters, '%
' for any primitive type, + '***
' for any type, and '...
' for any number of arguments.- fieldname and methodname can contain wildcards as well: + '
+?
' for a single character and '*
' + for any number of characters.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/retrace/examples.html b/docs/manual/retrace/examples.html new file mode 100644 index 000000000..2137e3a8c --- /dev/null +++ b/docs/manual/retrace/examples.html @@ -0,0 +1,345 @@ + + + + + + +ReTrace Examples + + + + +Examples
+ +Some typical example uses: ++
+ +- Restoring a stack trace with line numbers
+- Restoring a stack trace with line numbers + (verbose)
+- Restoring a stack trace without line numbers
+Restoring a stack trace with line numbers
+ +Assume for instance ProGuard itself has been obfuscated using the following +extra options: ++-printmapping proguard.map + +-renamesourcefileattribute ProGuard +-keepattributes SourceFile,LineNumberTable +++ +Now assume the processed application throws an exception, and we have saved the +stack trace in
proguard.trace
, shown below. Of course, in real +life ProGuard rarely throws exceptions, so this is a purposely generated +exception. :) + ++Exception in thread "main" java.lang.Error: Random exception + at pro.bY.a(ProGuard:576) + at pro.bO.a(ProGuard:431) + at pro.bj.a(ProGuard:145) + at pro.bY.a(ProGuard:522) + at pro.bj.a(ProGuard:129) + at pro.bN.a(ProGuard:125) + at pro.bY.a(ProGuard:251) + at pro.bY.a(ProGuard:229) + at pro.l.a(ProGuard:55) + at pro.bo.b(ProGuard:405) + at pro.ci.a(ProGuard:51) + at pro.bo.a(ProGuard:356) + at pro.be.a(ProGuard:109) + at pro.bo.a(ProGuard:356) + at pro.be.a(ProGuard:186) + at pro.bg.a(ProGuard:369) + at pro.bY.a(ProGuard:286) + at pro.bh.a(ProGuard:55) + at pro.bg.b(ProGuard:408) + at pro.bY.a(ProGuard:190) + at pro.bg.a(ProGuard:369) + at pro.M.a(ProGuard:110) + at pro.bY.a(ProGuard:449) + at pro.M.a(ProGuard:99) + at pro.bo.a(ProGuard:372) + at pro.bY.a(ProGuard:649) + at pro.bY.a(ProGuard:112) + at pro.P.a(ProGuard:66) + at pro.p.a(ProGuard:83) + at pro.bU.a(ProGuard:69) + at pro.bo.a(ProGuard:356) + at pro.J.a(ProGuard:149) + at pro.I.a(ProGuard:49) + at pro.J.a(ProGuard:105) + at pro.cf.c(ProGuard:370) + at pro.cf.a(ProGuard:317) + at pro.bc.a(ProGuard:55) + at proguard.ProGuard.a(ProGuard:363) + at proguard.ProGuard.c(ProGuard:187) + at proguard.ProGuard.b(ProGuard:385) + at proguard.ProGuard.main(ProGuard:429) +++ +We can then use the following command to recover the stack trace: +
+java -jar retrace.jar proguard.map proguard.trace +++ +The output will look as follows: +
+Exception in thread "main" java.lang.Error: Random exception + at proguard.shrink.UsageMarker.visitInstruction(ProGuard:576) + at proguard.classfile.instruction.GenericInstruction.accept(ProGuard:431) + at proguard.classfile.CodeAttrInfo.instructionsAccept(ProGuard:145) + at proguard.shrink.UsageMarker.visitCodeAttrInfo(ProGuard:522) + at proguard.classfile.CodeAttrInfo.accept(ProGuard:129) + at proguard.classfile.ProgramMemberInfo.attributesAccept(ProGuard:125) + at proguard.shrink.UsageMarker.visitMemberInfo(ProGuard:251) + at proguard.shrink.UsageMarker.visitProgramMethodInfo(ProGuard:229) + at proguard.classfile.ProgramMethodInfo.accept(ProGuard:55) + at proguard.classfile.ProgramClassFile.methodAccept(ProGuard:405) + at proguard.classfile.visitor.NamedMethodVisitor.visitProgramClassFile(ProGuard:51) + at proguard.classfile.ProgramClassFile.accept(ProGuard:356) + at proguard.classfile.visitor.ClassFileUpDownTraveler.visitProgramClassFile(ProGuard:109) + at proguard.classfile.ProgramClassFile.accept(ProGuard:356) + at proguard.classfile.visitor.ClassFileUpDownTraveler.visitLibraryClassFile(ProGuard:186) + at proguard.classfile.LibraryClassFile.accept(ProGuard:369) + at proguard.shrink.UsageMarker.visitLibraryMethodInfo(ProGuard:286) + at proguard.classfile.LibraryMethodInfo.accept(ProGuard:55) + at proguard.classfile.LibraryClassFile.methodsAccept(ProGuard:408) + at proguard.shrink.UsageMarker.visitLibraryClassFile(ProGuard:190) + at proguard.classfile.LibraryClassFile.accept(ProGuard:369) + at proguard.classfile.ClassCpInfo.referencedClassAccept(ProGuard:110) + at proguard.shrink.UsageMarker.visitClassCpInfo(ProGuard:449) + at proguard.classfile.ClassCpInfo.accept(ProGuard:99) + at proguard.classfile.ProgramClassFile.constantPoolEntryAccept(ProGuard:372) + at proguard.shrink.UsageMarker.markCpEntry(ProGuard:649) + at proguard.shrink.UsageMarker.visitProgramClassFile(ProGuard:112) + at proguard.classfile.visitor.VariableClassFileVisitor.visitProgramClassFile(ProGuard:66) + at proguard.classfile.visitor.MultiClassFileVisitor.visitProgramClassFile(ProGuard:83) + at proguard.classfile.visitor.FilteredClassFileVisitor.visitProgramClassFile(ProGuard:69) + at proguard.classfile.ProgramClassFile.accept(ProGuard:356) + at proguard.classfile.ClassPool.classFileAccept(ProGuard:149) + at proguard.classfile.visitor.NamedClassFileVisitor.visitClassPool(ProGuard:49) + at proguard.classfile.ClassPool.accept(ProGuard:105) + at proguard.KeepCommand.executeShrinkingPhase(ProGuard:370) + at proguard.KeepCommand.execute(ProGuard:317) + at proguard.CompoundCommand.execute(ProGuard:55) + at proguard.ProGuard.executeCommands(ProGuard:363) + at proguard.ProGuard.shrink(ProGuard:187) + at proguard.ProGuard.execute(ProGuard:385) + at proguard.ProGuard.main(ProGuard:429) ++ +Restoring a stack trace with line numbers (verbose)
+ +In the previous example, we could also use the verbose flag: ++java -jar retrace.jar -verbose proguard.map proguard.trace +++ +The output will then look as follows: +
+Exception in thread "main" java.lang.Error: Random exception + at proguard.shrink.UsageMarker.void visitInstruction(proguard.classfile.ClassFile,proguard.classfile.instruction.Instruction)(ProGuard:576) + at proguard.classfile.instruction.GenericInstruction.void accept(proguard.classfile.ClassFile,proguard.classfile.instruction.InstructionVisitor)(ProGuard:431) + at proguard.classfile.CodeAttrInfo.void instructionsAccept(proguard.classfile.ClassFile,proguard.classfile.instruction.InstructionVisitor)(ProGuard:145) + at proguard.shrink.UsageMarker.void visitCodeAttrInfo(proguard.classfile.ClassFile,proguard.classfile.CodeAttrInfo)(ProGuard:522) + at proguard.classfile.CodeAttrInfo.void accept(proguard.classfile.ClassFile,proguard.classfile.visitor.AttrInfoVisitor)(ProGuard:129) + at proguard.classfile.ProgramMemberInfo.void attributesAccept(proguard.classfile.ProgramClassFile,proguard.classfile.visitor.AttrInfoVisitor)(ProGuard:125) + at proguard.shrink.UsageMarker.void visitMemberInfo(proguard.classfile.ProgramClassFile,proguard.classfile.ProgramMemberInfo)(ProGuard:251) + at proguard.shrink.UsageMarker.void visitProgramMethodInfo(proguard.classfile.ProgramClassFile,proguard.classfile.ProgramMethodInfo)(ProGuard:229) + at proguard.classfile.ProgramMethodInfo.void accept(proguard.classfile.ProgramClassFile,proguard.classfile.visitor.MemberInfoVisitor)(ProGuard:55) + at proguard.classfile.ProgramClassFile.void methodAccept(proguard.classfile.visitor.MemberInfoVisitor,java.lang.String,java.lang.String)(ProGuard:405) + at proguard.classfile.visitor.NamedMethodVisitor.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:51) + at proguard.classfile.ProgramClassFile.void accept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:356) + at proguard.classfile.visitor.ClassFileUpDownTraveler.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:109) + at proguard.classfile.ProgramClassFile.void accept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:356) + at proguard.classfile.visitor.ClassFileUpDownTraveler.void visitLibraryClassFile(proguard.classfile.LibraryClassFile)(ProGuard:186) + at proguard.classfile.LibraryClassFile.void accept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:369) + at proguard.shrink.UsageMarker.void visitLibraryMethodInfo(proguard.classfile.LibraryClassFile,proguard.classfile.LibraryMethodInfo)(ProGuard:286) + at proguard.classfile.LibraryMethodInfo.void accept(proguard.classfile.LibraryClassFile,proguard.classfile.visitor.MemberInfoVisitor)(ProGuard:55) + at proguard.classfile.LibraryClassFile.void methodsAccept(proguard.classfile.visitor.MemberInfoVisitor)(ProGuard:408) + at proguard.shrink.UsageMarker.void visitLibraryClassFile(proguard.classfile.LibraryClassFile)(ProGuard:190) + at proguard.classfile.LibraryClassFile.void accept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:369) + at proguard.classfile.ClassCpInfo.void referencedClassAccept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:110) + at proguard.shrink.UsageMarker.void visitClassCpInfo(proguard.classfile.ClassFile,proguard.classfile.ClassCpInfo)(ProGuard:449) + at proguard.classfile.ClassCpInfo.void accept(proguard.classfile.ClassFile,proguard.classfile.visitor.CpInfoVisitor)(ProGuard:99) + at proguard.classfile.ProgramClassFile.void constantPoolEntryAccept(proguard.classfile.visitor.CpInfoVisitor,int)(ProGuard:372) + at proguard.shrink.UsageMarker.void markCpEntry(proguard.classfile.ClassFile,int)(ProGuard:649) + at proguard.shrink.UsageMarker.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:112) + at proguard.classfile.visitor.VariableClassFileVisitor.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:66) + at proguard.classfile.visitor.MultiClassFileVisitor.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:83) + at proguard.classfile.visitor.FilteredClassFileVisitor.void visitProgramClassFile(proguard.classfile.ProgramClassFile)(ProGuard:69) + at proguard.classfile.ProgramClassFile.void accept(proguard.classfile.visitor.ClassFileVisitor)(ProGuard:356) + at proguard.classfile.ClassPool.void classFileAccept(proguard.classfile.visitor.ClassFileVisitor,java.lang.String)(ProGuard:149) + at proguard.classfile.visitor.NamedClassFileVisitor.void visitClassPool(proguard.classfile.ClassPool)(ProGuard:49) + at proguard.classfile.ClassPool.void accept(proguard.classfile.visitor.ClassPoolVisitor)(ProGuard:105) + at proguard.KeepCommand.void executeShrinkingPhase(proguard.classfile.ClassPool,proguard.classfile.ClassPool)(ProGuard:370) + at proguard.KeepCommand.void execute(int,proguard.classfile.ClassPool,proguard.classfile.ClassPool)(ProGuard:317) + at proguard.CompoundCommand.void execute(int,proguard.classfile.ClassPool,proguard.classfile.ClassPool)(ProGuard:55) + at proguard.ProGuard.void executeCommands(int)(ProGuard:363) + at proguard.ProGuard.void shrink()(ProGuard:187) + at proguard.ProGuard.void execute(java.lang.String[])(ProGuard:385) + at proguard.ProGuard.void main(java.lang.String[])(ProGuard:429) ++ + +Restoring a stack trace without line numbers
+ +Assume for instance ProGuard itself has been obfuscated using the following +extra options, this time without preserving the line number tables: ++-printmapping proguard.map +++ +A stack trace
proguard.trace
will then lack line number +information: ++Exception in thread "main" java.lang.Error: Random exception + at pro.bY.a(Unknown Source) + at pro.bO.a(Unknown Source) + at pro.bj.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.bj.a(Unknown Source) + at pro.bN.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.l.a(Unknown Source) + at pro.bo.b(Unknown Source) + at pro.ci.a(Unknown Source) + at pro.bo.a(Unknown Source) + at pro.be.a(Unknown Source) + at pro.bo.a(Unknown Source) + at pro.be.a(Unknown Source) + at pro.bg.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.bh.a(Unknown Source) + at pro.bg.b(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.bg.a(Unknown Source) + at pro.M.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.M.a(Unknown Source) + at pro.bo.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.bY.a(Unknown Source) + at pro.P.a(Unknown Source) + at pro.p.a(Unknown Source) + at pro.bU.a(Unknown Source) + at pro.bo.a(Unknown Source) + at pro.J.a(Unknown Source) + at pro.I.a(Unknown Source) + at pro.J.a(Unknown Source) + at pro.cf.c(Unknown Source) + at pro.cf.a(Unknown Source) + at pro.bc.a(Unknown Source) + at proguard.ProGuard.a(Unknown Source) + at proguard.ProGuard.c(Unknown Source) + at proguard.ProGuard.b(Unknown Source) + at proguard.ProGuard.main(Unknown Source) +++ +We can still use the same command to recover the stack trace: +
+java -jar retrace.jar proguard.map proguard.trace +++ +The output will now give a list of alternative original method names for each +ambiguous obfuscated method name: +
+Exception in thread "main" java.lang.Error: Random exception + at proguard.shrink.UsageMarker.visitProgramClassFile(Unknown Source) + visitLibraryClassFile + visitProgramFieldInfo + visitProgramMethodInfo + visitMemberInfo + visitLibraryFieldInfo + visitLibraryMethodInfo + visitIntegerCpInfo + visitLongCpInfo + visitFloatCpInfo + visitDoubleCpInfo + visitStringCpInfo + visitUtf8CpInfo + visitFieldrefCpInfo + visitInterfaceMethodrefCpInfo + visitMethodrefCpInfo + visitClassCpInfo + visitNameAndTypeCpInfo + visitUnknownAttrInfo + visitInnerClassesAttrInfo + visitConstantValueAttrInfo + visitExceptionsAttrInfo + visitCodeAttrInfo + visitLineNumberTableAttrInfo + visitLocalVariableTableAttrInfo + visitSourceFileAttrInfo + visitDeprecatedAttrInfo + visitSyntheticAttrInfo + visitInstruction + visitCpInstruction + visitExceptionInfo + visitInnerClassesInfo + visitLocalVariableInfo + markCpEntry + markAsUnused + isUsed + at proguard.classfile.instruction.GenericInstruction.create(Unknown Source) + isWide + getLength + accept + at proguard.classfile.CodeAttrInfo.getAttribute(Unknown Source) + getAttrInfoLength + readInfo + accept + instructionsAccept + exceptionsAccept + [...] + at proguard.KeepCommand.executeShrinkingPhase(Unknown Source) + access$100 + at proguard.KeepCommand.keepField(Unknown Source) + ensureMultiClassFileVisitorForMembers + execute + executeObfuscationPhase + access$002 + access$000 + access$102 + access$108 + at proguard.CompoundCommand.addCommand(Unknown Source) + execute + at proguard.ProGuard.readCommands(Unknown Source) + obfuscate + executeCommands + at proguard.ProGuard.shrink(Unknown Source) + at proguard.ProGuard.check(Unknown Source) + execute + at proguard.ProGuard.main(Unknown Source) ++ +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/manual/retrace/index.html b/docs/manual/retrace/index.html new file mode 100644 index 000000000..47209df9e --- /dev/null +++ b/docs/manual/retrace/index.html @@ -0,0 +1,37 @@ + + + + + + +ReTrace Manual + + + + +ReTrace
+ ++
+ +- Introduction
+- Usage
+- Examples
+
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/retrace/introduction.html b/docs/manual/retrace/introduction.html new file mode 100644 index 000000000..381ad1fcd --- /dev/null +++ b/docs/manual/retrace/introduction.html @@ -0,0 +1,79 @@ + + + + + + +ReTrace Introduction + + + + +Introduction
+ +ReTrace is a companion tool for ProGuard that 'de-obfuscates' +stack traces. ++When an obfuscated program throws an exception, the resulting stack trace +typically isn't very informative. Class names and method names have been +replaced by short meaningless strings. Source file names and line numbers are +missing altogether. While this may be intentional, it can also be inconvenient +when debugging problems. +
+ +
+ +
++ + +Original code +- ProGuard → +Obfuscated code ++ + ++ ↓ +↓ ++ + +Mapping file +↓ ++ + +↓ +↓ ++ + +Readable stack trace +← ReTrace - +Obfuscated stack trace ++ReTrace can read an obfuscated stack trace and restore it to what it would +look like without obfuscation. The restoration is based on the mapping file +that ProGuard can write out during obfuscation. The mapping file links the +original class names and class member names to their obfuscated names. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/manual/retrace/usage.html b/docs/manual/retrace/usage.html new file mode 100644 index 000000000..6e7f6a8a2 --- /dev/null +++ b/docs/manual/retrace/usage.html @@ -0,0 +1,128 @@ + + + + + + +ReTrace Usage + + + + +Usage
+ +You can find the ReTrace jar in thelib
directory of the +ProGuard distribution. To run ReTrace, just type: ++
+
+Alternatively, thejava -jar retrace.jar
[options...] + mapping_file [stacktrace_file] +bin
directory contains some short Linux and +Windows scripts containing this command. These are the arguments: + ++
+ +The following options are supported: +- mapping_file
+ +- Specifies the name of the mapping file, produced by ProGuard with the + option + "
+ +-printmapping
mapping_file", + while obfuscating the application that produced the stack trace.- stacktrace_file
+ +- Optionally specifies the name of the file containing the stack trace. If + no file is specified, a stack trace is read from the standard input. Blank + lines and unrecognized lines are ignored, as far as possible.
++
+ +The restored stack trace is printed to the standard output. The completeness +of the restored stack trace depends on the presence of line number tables in +the obfuscated class files: + +- + +
-verbose
- Specifies to print out more informative stack traces that include not only + method names, but also method return types and arguments.
+ +- + +
-regex
regular_expression- Specifies the regular expression that is used to parse the lines in the + stack trace. Specifying a different regular expression allows to + de-obfuscate more general types of input than just stack traces. The + default is suitable for stack traces produced by most JVMs: +
++ (?:.*?\bat\s+%c.%m\s*\(.*?(?::%l)?\)\s*)|(?:(?:.*?[:"]\s+)?%c(?::.*)?) ++ The regular expression is a Java regular expression (cfr. the documentation + ofjava.util.regex.Pattern
), with a few additional wildcards: ++
+ Elements that match these wildcards are de-obfuscated, when possible. Note + that regular expressions must not contain any capturing groups. Use + non-capturing groups instead:+ + %c
matches a class name (e.g. + " myapplication.MyClass
").+ + %C
matches a class name with slashes (e.g. + " myapplication/MyClass
").+ + %t
matches a field type or method return type (e.g. + " myapplication.MyClass[]
").+ + %f
matches a field name (e.g. + " myField
").+ + %m
matches a method name (e.g. + " myMethod
").+ + %a
matches a list of method arguments (e.g. + " boolean,int
").+ + %l
matches a line number inside a method (e.g. + " 123
").(?:
...)
++
+- If all line numbers have been preserved while obfuscating the application, + ReTrace will be able to restore the stack trace completely.
+ +- If the line numbers have been removed, mapping obfuscated method names + back to their original names has become ambiguous. Retrace will list all + possible original method names for each line in the stack trace. The user + can then try to deduce the actual stack trace manually, based on the logic + of the program.
+ ++ +Preserving line number tables is explained in detail in this example in the ProGuard User Manual. +
+ +Unobfuscated elements and obfuscated elements for which no mapping is available +will be left unchanged. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/manual/sections.html b/docs/manual/sections.html new file mode 100644 index 000000000..1a6693d3a --- /dev/null +++ b/docs/manual/sections.html @@ -0,0 +1,54 @@ + + + + + + + +Sections + + + + + ++
+More Android code protection: + + + + diff --git a/docs/manual/style.css b/docs/manual/style.css new file mode 100644 index 000000000..8dae87db0 --- /dev/null +++ b/docs/manual/style.css @@ -0,0 +1,129 @@ +@charset "iso-8859-1"; + +/* Global settings. */ + +body +{ + background: #FFFFFF; +} + +h1 +{ + text-align: center; +} + +h2 +{ + background: #EEEEFF; + padding: 10px; +} + +dt +{ + padding: 6px; +} + +dt div +{ + color: grey; + float: right; +} + +dd +{ + padding: 6px; +} + +pre +{ + padding: 10px; + background: #E0E0E0; +} + +.spacious li +{ + padding: 8px; +} + +.shifted li +{ + margin-left: 50px; +} + +img.float +{ + float: left; +} + +a +{ + text-decoration: none; +} + +a.button +{ + color: #000000; + text-decoration: none; + background: #E0E0E0; + border: 1px outset #FFFFFF; + float: right; +} + +/* Settings for variable width code. */ + +p.code +{ + padding: 10px; + background: #E0E0E0; +} + + +/* Settings for diagrams. */ + +table.diagram +{ + padding: 8px; + border: none; + border-spacing: 2px; +} + +td.transparentblock +{ + text-align: center; + padding: 10px 0px; +} + +td.whiteblock +{ + width: 100px; + text-align: center; + border: 1px solid #C0C0C0; + background: #E0E0E0; + padding: 10px 0px; +} + +td.lightblock +{ + width: 100px; + text-align: center; + border: 1px solid #8888FF; + background: #BBBBFF; + padding: 20px 0px; +} + +td.darkblock +{ + width: 100px; + text-align: center; + background: #8888FF; + padding: 20px 0px; +} + +/* Settings for buttons. */ + +td.button +{ + background: #E0E0E0; + border: 1px outset #FFFFFF; + font-weight: bold; +} diff --git a/docs/manual/troubleshooting.html b/docs/manual/troubleshooting.html new file mode 100644 index 000000000..6b57aea1e --- /dev/null +++ b/docs/manual/troubleshooting.html @@ -0,0 +1,824 @@ + + + + + + ++ + + +
+With support of +
+ + + + +
+ + + +
ProGuard Troubleshooting + + + + +Troubleshooting
+ +While preparing a configuration for processing your code, you may bump into a +few problems. The following sections discuss some common issues and solutions: + +Problems while processing
++
+ +- Note: can't find dynamically referenced class
+- Note: ... calls '(...)Class.forName(variable).newInstance()'
+- Note: ... accesses a field/method '...' dynamically
+- Note: the configuration keeps the entry point '...', but not the descriptor class '...'
+- Note: the configuration doesn't specify which class members to keep for class '...'
+- Note: duplicate definition of program/library class
+- Warning: can't write resource ... Duplicate zip entry
+- Warning: can't find superclass or interface
+- Warning: can't find referenced class
+- Error: Can't find any super classes of ... (not even immediate super class ...)
+- Error: Can't find common super class of ... and ...
+- Warning: can't find referenced field/method
+- Warning: can't find enclosing class/method
+- Warning: library class ... depends on program class ...
+- Warning: class file ... unexpectedly contains class ...
+- Warning: ... is not being kept as ..., but remapped to ...
+- Warning: field/method ... can't be mapped to ...
+- Error: Unsupported class version number
+- Error: You have to specify '-keep' options
+- Error: Expecting class path separator ';' before 'Files\Java\...' (in Windows)
+- Error: Can't read [.../lib/rt.jar] (No such file or directory) (in MacOS X)
+- Error: Can't read ...
+- Error: Can't write ...
+- Internal problem starting the ProGuard GUI (Cannot write XdndAware property) (in Linux)
+- OutOfMemoryError
+- StackOverflowError
+- Unexpected error
+- Otherwise...
+Unexpected observations after processing
++
+ +- Disappearing classes
+- Classes or class members not being kept
+- Variable names not being obfuscated
+Problems while converting to Android Dalvik bytecode
+ + + +Problems while preverifying for Java Micro Edition
+ + + +Problems at run-time
++
+ + +- Stack traces without class names or line numbers
+- NoClassDefFoundError
+- ClassNotFoundException
+- NoSuchFieldException
+- NoSuchMethodException
+- MissingResourceException or NullPointerException
+- Disappearing annotations
+- Invalid or corrupt jarfile
+- InvalidJarIndexException: Invalid index
+- InvalidClassException, class loading error, or verification error (in Java Micro Edition)
+- Error: No Such Field or Method, Error verifying method (in a Java Micro Edition emulator)
+- Failing midlets (on a Java Micro Edition device)
+- Disappearing loops
+- SecurityException: SHA1 digest error
+- ClassCastException: class not an enum
- IllegalArgumentException: class not an enum type
+- ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy
+- CompilerError: duplicate addition
+- ClassFormatError: repetitive field name/signature
+- ClassFormatError: Invalid index in LocalVariableTable in class file
+- NoSuchMethodError or AbstractMethodError
+- VerifyError
+Problems while processing
+ +ProGuard may print out some notes and non-fatal warnings: + ++
+- Note: can't find dynamically referenced class
+ +- ProGuard can't find a class or interface that your code is accessing by + means of introspection. You should check if you want to add the jar that + contains this class.
+ +- Note: ... calls '(...)Class.forName(variable).newInstance()'
+ +- ProGuard lists all class casts of dynamically created class instances, + like "
+ +(MyClass)Class.forName(variable).newInstance()
". + Depending on your application, you may need to keep the mentioned classes + with an option like "-keep class MyClass
", or their + implementations with an option like "-keep class * implements + MyClass
". You can switch off these notes by specifying the +-dontnote
option.- Note: ... accesses a field/method '...' dynamically
+ +- ProGuard lists a number of constructs like + "
+ +.getField("myField")
". Depending on your application, you + may need to figure out where the mentioned class members are defined and + keep them with an option like "-keep class MyClass { MyFieldType + myField; }
". Otherwise, ProGuard might remove or obfuscate the + class members, since it can't know which ones they are exactly. It does + list possible candidates, for your information. You can switch off these + notes by specifying the-dontnote
option.- Note: the configuration keeps the entry point '...', but not the descriptor class '...'
+ +- Your configuration contains a
+ +-keep
option to preserve the + given method (or field), but no-keep
option for the given + class that is an argument type or return type in the method's descriptor. + You may then want to keep the class too. Otherwise, ProGuard will + obfuscate its name, thus changing the method's signature. The method might + then become unfindable as an entry point, e.g. if it is part of a public + API. You can switch off these notes by specifying the-dontnote
option.- Note: the configuration doesn't specify which class members to keep for class '...'
+ +- Your configuration contains + a
+ +-keepclassmembers/-keepclasseswithmembers
option to + preserve fields or methods in the given class, but it doesn't specify + which fields or methods. This way, the option simply won't have any + effect. You probably want to specify one or more fields or methods, as + usual between curly braces. You can specify all fields or methods with a + wildcard "*;
". You can switch off these notes by specifying + the-dontnote
option.- Note: duplicate definition of program/library class
+ +- Your program jars or library jars contain multiple definitions of the + listed classes. ProGuard continues processing as usual, only considering + the first definitions. The warning may be an indication of some problem + though, so it's advisable to remove the duplicates. A convenient way to do + so is by specifying filters on the input jars or library jars. You can + switch off these notes by specifying the
+ +-dontnote
option.- Warning: can't write resource ... Duplicate zip entry
+ +- Your input jars contain multiple resource files with the same name. + ProGuard continues copying the resource files as usual, skipping any files + with previously used names. Once more, the warning may be an indication of + some problem though, so it's advisable to remove the duplicates. A + convenient way to do so is by specifying filters on the input jars. There + is no option to switch off these warnings.
+ ++ +ProGuard may terminate when it encounters parsing errors or I/O errors, or +some more serious warnings: + +
+
+- Warning: can't find superclass or interface
+ +
Warning: can't find referenced class- A class in one of your program jars or library jars is referring to a + class or interface that is missing from the input. The output lists both + the referencing class(es) and the missing referenced class(es). There can + be a few reasons, with their own solutions: +
+ ++
+
+- If the missing class is referenced from your own code, you may have + forgotten to specify an essential library. Just like when compiling + all code from scratch, you must specify all libraries that the code is + referencing, directly or indirectly. If the library should be + processed and included in the output, you should specify it with +
+-injars
, otherwise you + should specify it with +-libraryjars
. ++ For example, if ProGuard complains that it can't find a +
java.lang
class, you have to make sure that you are + specifying the run-time library of your platform. For JSE, these are + typically packaged inlib/rt.jar
(vm.jar
for + IBM's JVM, andclasses.jar
in MacOS X). Other platforms + like JME and Android have their own run-time libraries. + The examples section provides more details + for the various platforms. ++ If ProGuard still complains that it can't find a +
javax.crypto
class, you probably still have to specify +jce.jar
, next to the more commonrt.jar
.- If the missing class is referenced from a pre-compiled third-party + library, and your original code runs fine without it, then the missing + dependency doesn't seem to hurt. The cleanest solution is to + filter out the referencing + class or classes from the input, with a filter like "
+-injars + myapplication.jar(!somepackage/SomeUnusedReferencingClass.class)
". + ProGuard will then skip this class entirely in the input, and it will + not bump into the problem of its missing reference. However, you may + then have to filter out other classes that are in turn referencing the + removed class. In practice, this works best if you can filter out + entire unused packages at once, with a wildcard filter like + "-injars + myapplication.jar(!someunusedpackage/**)
".- If you don't feel like filtering out the problematic classes, you can + try your luck with the
+-ignorewarnings
+ option, or even + the-dontwarn
option. + Only use these options if you really know what you're doing though.+ This last solution is commonly necessary in the standard Android build + process. The standard build script automatically passes the libraries that + it can find in the
libs
directory to ProGuard. Unfortunately, + many third-party libraries refer to other libraries that are not actually + used and not present. This works fine in debug builds, but in release + builds, ProGuard expects all libraries, so it can perform a proper static + analysis. For example, if ProGuard complains that it can't find + ajava.awt
class, then some library that you are using is + referring tojava.awt
. This is a bit shady, since Android + doesn't have this package at all, but if your application works anyway, + you can let ProGuard accept it with "-dontwarn + java.awt.**
".- Error: Can't find any super classes of ... (not even immediate super class ...)
+ +
Error: Can't find common super class of ... and ...- It seems like you tried to avoid the warnings from the previous paragraph + by specifying +
+ +-ignorewarnings
+ or-dontwarn
, but it didn't + work out. ProGuard's optimization step and preverification step really + need the missing classes to make sense of the code. Preferably, you would + solve the problem by adding the missing library, as discussed. If you're + sure the class that references the missing class isn't used either, you + could also try filtering it out from the input, by adding a filter to the + corresponding-injars
option: + "-injars + myapplication.jar(!somepackage/SomeUnusedClass.class)
". As a final + solution, you could switch off optimization + (-dontoptimize
) and + preverification + (-dontpreverify
).- Warning: can't find referenced field/method
+ +- A class in one of your program jars is referring to a field or a method + that is missing from the input, even though its class is present. The + output lists both the referencing class and the missing referenced class + member. There can be a few reasons, with their own solutions: +
+ ++
+
- If there are unresolved references to class members in program + classes, your compiled class files are most likely inconsistent. + Possibly, some class file didn't get recompiled properly, or some + class file was left behind after its source file was removed. Try + removing all compiled class files and rebuilding your project.
+- If there are unresolved references to class members in library + classes, your compiled class files are inconsistent with the + libraries. You may need to recompile the class files, or otherwise + upgrade the libraries to consistent versions. +
++ For example, if you're developing for Android, and ProGuard complains + that it can't find a run-time method that is only available in recent + versions of Android, you should change the target in +
project.properties
to that recent version. ++ Alternatively, you may get away with ignoring the inconsistency with + the options +
-ignorewarnings
+ or even +-dontwarn
. For + instance if the code contains a class to optionally support recent + versions of Android, you can specify "-dontwarn + mypackage.MySupportClass
".- If your program classes reside in the same packages as library classes, + and refer to their package visible class members, then you should also + specify the +
+-dontskipnonpubliclibraryclassmembers
+ option.- Warning: can't find enclosing class/method
+ +- If there are unresolved references to classes that are defined inside + methods in your input, once more, your compiled class files are most likely + inconsistent. Possibly, some class file didn't get recompiled properly, or + some class file was left behind after its source file was removed. Try + removing all compiled class files and rebuilding your project.
+ +- Warning: library class ... depends on program class ...
+ +- If any of your library classes depend on your program classes, by + extending, implementing or just referencing them, your processed code will + generally be unusable. Program classes can depend on library classes, but + not the other way around. Program classes are processed, while library + classes always remain unchanged. It is therefore impossible to adapt + references from library classes to program classes, for instance if the + program classes are renamed. You should define a clean separation between + program code (specified with
+ +-injars
) and library code + (specified with-libraryjars
), and try + again. ++ On Android, it is not uncommon that sloppy libraries contain duplicates of + classes that are already present in the Android run-time + (e.g.
org.json
,org.xml
,org.xmlpull
, +org.w3c.dom
, ororg.apache.http
). You must remove + these classes from your libraries, since they are possibly inconsistent, + and the run-time libraries would get precedence anyway.- Warning: class file ... unexpectedly contains class ...
+ +- The given class file contains a definition for the given class, but the + directory name of the file doesn't correspond to the package name of the + class. ProGuard will accept the class definition, but the current + implementation will not write out the processed version. Please make sure + your input classes are packaged correctly. Notably, class files that are + in the
+ +WEB-INF/classes
directory in a war should be packaged + in a jar and put in theWEB-INF/lib
directory. If you don't + mind these classes not being written to the output, you can specify the-ignorewarnings
option, + or even the-dontwarn
+ option.- Warning: ... is not being kept as ..., but remapped to ...
+ +- There is a conflict between a
+ +-keep
option in the + configuration, and the mapping file, in the obfuscation step. The given + class name or class member name can't be kept by its original name, as + specified in the configuration, but it has to be mapped to the other given + name, as specified in the mapping file. You should adapt your + configuration or your mapping file to remove the conflict. Alternatively, + if you're sure the renaming won't hurt, you can specify the-ignorewarnings
option, + or even the-dontwarn
+ option.- Warning: field/method ... can't be mapped to ...
+ +- There is a conflict between some new program code and the mapping file, in + the obfuscation step. The given class member can't be mapped to the given + name, because it would conflict with another class member that is already + being mapped to the same name. This can happen if you are performing + incremental obfuscation, applying an obfuscation mapping file from an + initial obfuscation step. For instance, some new class may have been added + that extends two existing classes, introducing a conflict in the name + space of its class members. If you're sure the class member receiving + another name than the one specified won't hurt, you can specify the
+ +-ignorewarnings
option, + or even the-dontwarn
+ option. Note that you should always use the-useuniqueclassmembernames
+ option in the initial obfuscation step, in order to reduce the risk of + conflicts.- Error: Unsupported class version number
+ +- You are trying to process class files compiled for a recent version of + Java that your copy of ProGuard doesn't support yet. You + should check + on-line if there is a more recent release.
+ +- Error: You have to specify '-keep' options
+ +- You either forgot to specify
+ +-keep
options, or you mistyped the + class names. ProGuard has to know exactly what you want to keep: an + application, an applet, a servlet, a midlet,..., or any combination of + these. Without the proper seed specifications, ProGuard would shrink, + optimize, or obfuscate all class files away.- Error: Expecting class path separator ';' before 'Files\Java\...' (in Windows)
+ +- If the path of your run-time jar contains spaces, like in "Program Files", + you have to enclose it with single or double quotes, as explained in the + section on file names. This is actually + true for all file names containing special characters, on all + platforms.
+ +- Error: Can't read [.../lib/rt.jar] (No such file or directory) (in MacOS X)
+ +- In MacOS X, the run-time classes may be in a different place than on most + other platforms. You'll then have to adapt your configuration, replacing + the path
+ +<java.home>/lib/rt.jar
by +<java.home>/../Classes/classes.jar
.- Error: Can't read ...
+ +- ProGuard can't read the specified file or directory. Double-check that the + name is correct in your configuration, that the file is readable, and that + it is not corrupt. An additional message "Unexpected end of ZLIB input + stream" suggests that the file is truncated. You should then make sure + that the file is complete on disk when ProGuard starts (asynchronous + copying? unflushed buffer or cache?), and that it is not somehow + overwritten by ProGuard's own output.
+ +- Error: Can't write ...
+ +- ProGuard can't write the specified file or directory. Double-check that + the name is correct in your configuration and that the file is + writable.
+ +- Internal problem starting the ProGuard GUI (Cannot write XdndAware property) (in Linux)
+ +- In Linux, at least with Java 6, the GUI may not start properly, due to + Sun + Bug #7027598. The work-around at this time is to specify the JVM + option
+ +-DsuppressSwingDropSupport=true
when running the + GUI.+ +Should ProGuard crash while processing your application: + +
+
+- OutOfMemoryError
+ +- You can try increasing the heap size of the Java virtual machine (with the + usual
+ +-Xms
and-Xmx
options). You can also + reduce the amount of memory that ProGuard needs by removing unnecessary + library jars from your configuration, or by filtering out unused library + packages and classes. Remember that only classes or interfaces that are + extended or implemented by classes in your input jars are required.- StackOverflowError
+ +- This error might occur when processing a large code base on Windows + (surprisingly, not so easily on Linux). In theory, increasing the stack + size of the Java virtual machine (with the usual
+ +-Xss
option) + should help too. In practice however, the-Xss
setting + doesn't have any effect on the main thread, due to Sun Bug + #4362291. As a result, this solution will only work when running + ProGuard in a different thread, e.g. from its GUI.- Unexpected error
+ +- ProGuard has encountered an unexpected condition, typically in the + optimization step. It may or may not recover. You should be able to avoid + it using the
+ +-dontoptimize
option. In + any case, please report the problem, preferably with the simplest example + that causes ProGuard to crash.- Otherwise...
+ +- Maybe your class files are corrupt. See if recompiling them and trying + again helps. If not, please report the problem, preferably with the + simplest example that causes ProGuard to crash.
+ ++ +
Unexpected observations after processing
+ +If ProGuard seems to run fine, but your processed code doesn't look right, +there might be a couple of reasons: + ++
+ +- Disappearing classes
+ +- If you are working on Windows and it looks like some classes have + disappeared from your output, you should make sure you're not writing your + output class files to a directory (or unpacking the output jar). On + platforms with case-insensitive file systems, such as Windows, unpacking + tools often let class files with similar lower-case and upper-case names + overwrite each other. If you really can't switch to a different operating + system, you could consider using ProGuard's
+ +-dontusemixedcaseclassnames
+ option. ++ Also, you should make sure your class files are in directories that + correspond to their package names. ProGuard will read misplaced class + files, but it will currently not write their processed versions. Notably, + class files that are in the
WEB-INF/classes
directory in a + war should be packaged in a jar and put in theWEB-INF/lib
+ directory.- Classes or class members not being kept
+ +- If ProGuard is not keeping the right classes or class members, make sure + you are using fully qualified class names. If the package name of some + class is missing, ProGuard won't match the elements that you might be + expecting. It may help to double-check for typos too. You can use the
+ +-printseeds
option to see + which elements are being kept exactly. ++ If you are using marker interfaces to keep other classes, the marker + interfaces themselves are probably being removed in the shrinking step. + You should therefore always explicitly keep any marker interfaces, with + an option like "
-keep interface MyMarkerInterface
". ++ Similarly, if you are keeping classes based on annotations, you may have + to avoid that the annotation classes themselves are removed in the + shrinking step. You should package the annotation classes as a library, or + explicitly keep them in your program code with an option like "
-keep + @interface *
".- Variable names not being obfuscated
+ +- If the names of the local variables and parameters in your obfuscated code + don't look obfuscated, because they suspiciously resemble the names of + their types, it's probably because the decompiler that you are using is + coming up with those names. ProGuard's obfuscation step does remove the + original names entirely, unless you explicitly keep the +
+ +LocalVariableTable
orLocalVariableTypeTable
+ attributes.Problems while converting to Android Dalvik bytecode
+ +If ProGuard seems to run fine, but the dx tool in the Android SDK subsequently +fails with an error: + ++
+ +- SimException: local variable type mismatch
+ +- This error indicates that ProGuard's optimization step has not been able + to maintain the correct debug information about local variables. This can + happen if some code is optimized radically. Possible work-arounds: let the + java compiler not produce debug information (
+ +-g:none
), or let + ProGuard's obfuscation step remove the debug information again + (by not keeping the attributesLocalVariableTable
+ andLocalVariableTypeTable
+ with-keepattributes
), + or otherwise just disable optimization + (-dontoptimize
).- Conversion to Dalvik format failed with error 1
+ +- This error may have various causes, but if dx is tripping over some code + processed by ProGuard, you should make sure that you are using the latest + version of ProGuard. You can just copy the ProGuard jars + to
+ +android-sdk/tools/proguard/lib
. If that doesn't help, + please report the problem, preferably with the simplest example that still + brings out the error.Problems while preverifying for Java Micro Edition
+ +If ProGuard seems to run fine, but the external preverifier subsequently +produces errors, it's usually for a single reason: + ++
+ +Note that it is no longer necessary to use an external preverifier. With the +- InvalidClassException, class loading error, or verification error
+ +- If you get any such message from the preverifier, you are probably working + on a platform with a case-insensitive file system, such as Windows. The +
+ +preverify
tool always unpacks the jars, so class files with + similar lower-case and upper-case names overwrite each other. You can use + ProGuard's-dontusemixedcaseclassnames
+ option to work around this problem. ++ If the above doesn't help, there is probably a bug in the optimization + step of ProGuard. Make sure you are using the latest version. You should + be able to work around the problem by using the
-dontoptimize
option. You + can check the bug database to see if it is a known problem (often with a + fix). Otherwise, please report it, preferably with the simplest example on + which you can find ProGuard to fail.-microedition
option, +ProGuard will preverify the class files for Java Micro Edition. ++ +
Problems at run-time
+ +If ProGuard runs fine, but your processed application doesn't work, there +might be several reasons: + ++
+ +- Stack traces without class names or line numbers
+ +- If your stack traces don't contain any class names or lines numbers, + even though you are keeping the proper attributes, make sure this debugging + information is present in your compiled code to start with. Notably the Ant + javac task has debugging information switched off by default.
+ +- NoClassDefFoundError
+ +- Your class path is probably incorrect. It should at least contain all + library jars and, of course, your processed program jar.
+ +- ClassNotFoundException
+ +- Your code is probably calling
+ +Class.forName
, trying to create + the missing class dynamically. ProGuard can only detect constant name + arguments, likeClass.forName("mypackage.MyClass")
. For + variable name arguments likeClass.forName(someClass)
, you + have to keep all possible classes using the appropriate-keep
option, e.g. "-keep + class mypackage.MyClass
" or "-keep class * implements + mypackage.MyInterface
".- NoSuchFieldException
+ +- Your code is probably calling something like +
+ +myClass.getField
, trying to find some field dynamically. + Since ProGuard can't always detect this automatically, you have to keep + the missing field in using the + appropriate-keep
option, e.g. + "-keepclassmembers class mypackage.MyClass { int myField; + }
".- NoSuchMethodException
+ +- Your code is probably calling something like +
+ +myClass.getMethod
, trying to find some method dynamically. + Since ProGuard can't always detect this automatically, you have to keep + the missing method in using the + appropriate-keep
option, e.g. + "-keepclassmembers class mypackage.MyClass { void myMethod(); + }
". ++ More specifically, if the method reported as missing is +
values
orvalueOf
, you probably have to keep + some methods related to enumerations.- MissingResourceException or NullPointerException
+ +- Your processed code may be unable to find some resource files. ProGuard + simply copies resource files over from the input jars to the output jars. + Their names and contents remain unchanged, unless you specify the options +
+ +-adaptresourcefilenames
+ and/or-adaptresourcefilecontents
. ++ Furthermore, directory entries in jar files aren't copied, unless you + specify the option
-keepdirectories
. + Note that Sun advises against callingClass.getResource()
for + directories (Sun + Bug #4761949).- Disappearing annotations
+ +- By default, the obfuscation step removes all annotations. If your + application relies on annotations to function properly, you should + explicitly keep them with +
+ +-keepattributes + *Annotation*
.- Invalid or corrupt jarfile
+ +- You are probably starting your application with the java option +
+ +-jar
instead of the option-classpath
. The java + virtual machine returns with this error message if your jar doesn't + contain a manifest file (META-INF/MANIFEST.MF
), if the + manifest file doesn't specify a main class (Main-Class:
...), + or if the jar doesn't contain this main class. You should then make sure + that the input jar contains a valid manifest file to start with, that this + manifest file is the one that is copied (the first manifest file that is + encountered), and that the main class is kept in your configuration,- InvalidJarIndexException: Invalid index
+ +- At least one of your processed jar files contains an index file +
+ +META-INF/INDEX.LIST
, listing all class files in the jar. + ProGuard by default copies files like these unchanged. ProGuard may however + remove or rename classes, thus invalidating the file. You should filter the + index file out of the input + (-injars in.jar(!META-INF/INDEX.LIST)
) or update the file + after having applied ProGuard (jar -i out.jar
). +- InvalidClassException, class loading error, or verification error (in Java Micro Edition)
+ +- If you get such an error in Java Micro Edition, you may have forgotten to + specify the
+ +-microedition
option, so + the processed class files are preverified properly.- Error: No Such Field or Method, Error verifying method (in a Java Micro Edition emulator)
+ +- If you get such a message in a Motorola or Sony Ericsson phone emulator, + it's because these emulators don't like packageless classes and/or + overloaded fields and methods. You can work around it by not using the + options
+ +-repackageclasses + ''
and-overloadaggressively
. + If you're using the JME WTK plugin, you can adapt the configuration +proguard/wtk/default.pro
that's inside the +proguard.jar
.- Failing midlets (on a Java Micro Edition device)
+ +- If your midlet runs in an emulator and on some devices, but not on some + other devices, this is probably due to a bug in the latter devices. For + some older Motorola and Nokia phones, you might try specifying the
+ +-useuniqueclassmembernames
+ option. It avoids overloading class member names, which triggers a bug in + their java virtual machine. ++ You might also try using the
-dontusemixedcaseclassnames
+ option. Even if the midlet has been properly processed and then + preverified on a case-sensitive file system, the device itself might not + like the mixed-case class names. Notably, the Nokia N-Gage emulator works + fine, but the actual device seems to exhibit this problem.- Disappearing loops
+ +- If your code contains empty busy-waiting loops, ProGuard's optimization + step may remove them. More specifically, this happens if a loop + continuously checks the value of a non-volatile field that is changed in a + different thread. The specifications of the Java Virtual Machine require + that you always mark fields that are accessed across different threads + without further synchronization as
+ +volatile
. If this is not + possible for some reason, you'll have to switch off optimization using the +-dontoptimize
+ option.- SecurityException: SHA1 digest error
+ +- You may have forgotten to sign your program jar after having + processed it with ProGuard.
+ +- ClassCastException: class not an enum, or
+ +
IllegalArgumentException: class not an enum type- You should make sure you're preserving the special methods of enumeration + types, which the run-time environment calls by introspection. The required + options are shown in the examples.
+ +- ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy
+ +- You are probably processing annotations involving enumerations. Again, you + should make sure you're preserving the special methods of the enumeration + type, as shown in the examples.
+ +- CompilerError: duplicate addition
+ +- You are probably compiling or running some code that has been obfuscated + with the
+ +-overloadaggressively
+ option. This option triggers a bug in +sun.tools.java.MethodSet.add
in Sun's JDK 1.2.2, which is + used for (dynamic) compilation. You should then avoid this option.- ClassFormatError: repetitive field name/signature
+ +- You are probably processing some code that has been obfuscated before with + the
+ +-overloadaggressively
+ option. You should then use the same option again in the second processing + round.- ClassFormatError: Invalid index in LocalVariableTable in class file
+ +- If you are keeping the
+ +LocalVariableTable
or +LocalVariableTypeTable
attributes, ProGuard's optimizing step + is sometimes unable to update them consistently. You should then let the + obfuscation step remove these attributes or disable the optimization + step.- NoSuchMethodError or AbstractMethodError
+ +- You should make sure you're not writing your output class files to a + directory on a platform with a case-insensitive file system, such as + Windows. Please refer to the section about disappearing classes for details. +
+ ++ Furthermore, you should check whether you have specified your program jars + and library jars properly. Program classes can refer to library classes, + but not the other way around. +
+ If all of this seems ok, perhaps there's a bug in ProGuard (gasp!). If so, + please report it, preferably with the simplest example on which you can + find ProGuard to fail.
- VerifyError
+ +- Verification errors when executing a program are almost certainly the + result of a bug in the optimization step of ProGuard. Make sure you are + using the latest version. You should be able to work around the problem by + using the
+ +-dontoptimize
+ option. You can check the bug database to see if it is a known problem + (often with a fix). Otherwise, please report it, preferably with the + simplest example on which ProGuard fails.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/usage.html b/docs/manual/usage.html new file mode 100644 index 000000000..7d3a5bb3d --- /dev/null +++ b/docs/manual/usage.html @@ -0,0 +1,1246 @@ + + + + + + +ProGuard Usage + + + + +Usage
+ +To run ProGuard, just type: ++
+You can find the ProGuard jar in thejava -jar proguard.jar
options ... +lib
directory of the +ProGuard distribution. Alternatively, thebin
directory contains +some short Linux and Windows scripts containing this command. Typically, you'll +put most options in a configuration file (say,myconfig.pro
), and +just call: ++
+You can combine command line options and options from configuration files. For +instance: +java -jar proguard.jar @myconfig.pro
++
+java -jar proguard.jar @myconfig.pro -verbose
++You can add comments in a configuration file, starting with a +
#
character and continuing until the end of the line. ++Extra whitespace between words and delimiters is ignored. File names with +spaces or special characters should be quoted with single or double quotes. +
+Options can be grouped arbitrarily in arguments on the command line and in +lines in configuration files. This means that you can quote arbitrary sections +of command line options, to avoid shell expansion of special characters, for +instance. +
+The order of the options is generally irrelevant. For quick experiments, you +can abbreviate them to their first unique characters. +
+ +The sections below provide more details: +
+
+ +- Input/Output Options
+- Keep Options
+- Shrinking Options
+- Optimization Options
+- Obfuscation Options
+- Preverification Options
+- General Options
+- Class Paths
+- File Names
+- File Filters
+- Filters
+- Overview of
+Keep
Options- Keep Option Modifiers
+- Class Specifications
+Input/Output Options
+ ++
+- + +
@
filename- Short for '
+ +-include
+ filename'.- + +
-include
+ filename- Recursively reads configuration options from the given file + filename.
+ +- + +
-basedirectory
+ directoryname- Specifies the base directory for all subsequent relative file names in + these configuration arguments or this configuration file.
+ +- + +
-injars
+ class_path- Specifies the input jars (or wars, ears, zips, or directories) of the + application to be processed. The class files in these jars will be + processed and written to the output jars. By default, any non-class files + will be copied without changes. Please be aware of any temporary files + (e.g. created by IDEs), especially if you are reading your input files + straight from directories. The entries in the class path can be filtered, + as explained in the filters section. For better + readability, class path entries can be specified using multiple +
+ +-injars
options.- + +
-outjars
+ class_path- Specifies the names of the output jars (or wars, ears, zips, or + directories). The processed input of the preceding
+ +-injars
+ options will be written to the named jars. This allows you to collect the + contents of groups of input jars into corresponding groups of output jars. + In addition, the output entries can be filtered, as explained in + the filters section. Each processed class file + or resource file is then written to the first output entry with a matching + filter, within the group of output jars. ++ You must avoid letting the output files overwrite any input files. For + better readability, class path entries can be specified using multiple +
-outjars
options. Without any-outjars
options, + no jars will be written.- + +
-libraryjars
+ class_path- Specifies the library jars (or wars, ears, zips, or directories) of the + application to be processed. The files in these jars will not be included + in the output jars. The specified library jars should at least contain the + class files that are extended by application class files. Library + class files that are only called needn't be present, although their + presence can improve the results of the optimization step. The entries in + the class path can be filtered, as explained in the filters section. For better readability, class path + entries can be specified using multiple
+ +-libraryjars
options. ++ Please note that the boot path and the class path set for running ProGuard + are not considered when looking for library classes. This means that you + explicitly have to specify the run-time jar that your code will use. + Although this may seem cumbersome, it allows you to process applications + targeted at different run-time environments. For example, you can process + J2SE applications as well as JME midlets or Android apps, just by + specifying the appropriate run-time jar.
- + +
-skipnonpubliclibraryclasses
- Specifies to skip non-public classes while reading library jars, to speed + up processing and reduce memory usage of ProGuard. By default, ProGuard + reads non-public and public library classes alike. However, non-public + classes are often not relevant, if they don't affect the actual program + code in the input jars. Ignoring them then speeds up ProGuard, without + affecting the output. Unfortunately, some libraries, including recent JSE + run-time libraries, contain non-public library classes that are extended + by public library classes. You then can't use this option. ProGuard will + print out warnings if it can't find classes due to this option being + set.
+ +- + +
-dontskipnonpubliclibraryclasses
- Specifies not to ignore non-public library classes. As of version 4.5, this + is the default setting.
+ +- + +
-dontskipnonpubliclibraryclassmembers
- Specifies not to ignore package visible library class members (fields and + methods). By default, ProGuard skips these class members while parsing + library classes, as program classes will generally not refer to them. + Sometimes however, program classes reside in the same packages as library + classes, and they do refer to their package visible class members. In + those cases, it can be useful to actually read the class members, in order + to make sure the processed code remains consistent.
+ +- + +
-keepdirectories
+ [directory_filter]- Specifies the directories to be kept in the output jars (or wars, ears, + zips, or directories). By default, directory entries are removed. This + reduces the jar size, but it may break your program if the code tries to + find them with constructs like + "
+ +mypackage.MyClass.class.getResource("")
". You'll then want to + keep the directory corresponding to the package, "-keepdirectories + mypackage
". If the option is specified without a filter, all + directories are kept. With a filter, only matching directories are + kept.- + +
-target
version- Specifies the version number to be set in the processed class files. The + version number can be one of
+ +1.0
,1.1
, +1.2
,1.3
,1.4
,1.5
(or + just5
),1.6
(or just6
), or +1.7
(or just7
). By default, the version numbers + of the class files are left unchanged. For example, you may want to + upgrade class files to Java 6, by + changing their version numbers and having them preverified.- + +
-forceprocessing
- Specifies to process the input, even if the output seems up to date. The + up-to-dateness test is based on a comparison of the date stamps of the + specified input, output, and configuration files or directories.
+ ++ +
Keep Options
+ ++
+- + +
-keep
+ [,modifier,...] + class_specification- Specifies classes and class members (fields and methods) to be preserved + as entry points to your code. For example, in order to keep an application, you can specify + the main class along with its main method. In order to process a library, you should specify all + publicly accessible elements.
+ +- + +
-keepclassmembers
+ [,modifier,...] + class_specification- Specifies class members to be preserved, if their classes are preserved as + well. For example, you may want to keep all serialization fields and + methods of classes that implement the
+ +Serializable
+ interface.- + +
-keepclasseswithmembers
+ [,modifier,...] + class_specification- Specifies classes and class members to be preserved, on the condition that + all of the specified class members are present. For example, you may want + to keep all applications that + have a main method, without having to list them explicitly.
+ +- + +
-keepnames
+ class_specification- Short for
+ +-keep
,allowshrinking
+ class_specification ++ Specifies classes and class members whose names are to be preserved, if + they aren't removed in the shrinking phase. For example, you may want to + keep all class names of classes + that implement the
Serializable
interface, so that the + processed code remains compatible with any originally serialized classes. + Classes that aren't used at all can still be removed. Only applicable when + obfuscating.- + +
-keepclassmembernames
+ class_specification- Short for
+ +-keepclassmembers
,allowshrinking
+ class_specification ++ Specifies class members whose names are to be preserved, if they aren't + removed in the shrinking phase. For example, you may want to preserve the + name of the synthetic
class$
methods + when processing a library compiled by + JDK 1.2 or older, so obfuscators can detect it again when processing an + application that uses the processed library (although ProGuard itself + doesn't need this). Only applicable when obfuscating.- + +
-keepclasseswithmembernames
+ class_specification- Short for
+ +-keepclasseswithmembers
,allowshrinking
+ class_specification ++ Specifies classes and class members whose names are to be preserved, on + the condition that all of the specified class members are present after + the shrinking phase. For example, you may want to keep all native method names and the names + of their classes, so that the processed code can still link with the + native library code. Native methods that aren't used at all can still be + removed. If a class file is used, but none of its native methods are, its + name will still be obfuscated. Only applicable when obfuscating.
- + +
-printseeds
+ [filename]- Specifies to exhaustively list classes and class members matched by the + various
+ +-keep
options. The list is printed to the standard + output or to the given file. The list can be useful to verify if the + intended class members are really found, especially if you're using + wildcards. For example, you may want to list all the applications or all the applets that you are keeping.+ +
Shrinking Options
+ ++
+- + +
-dontshrink
- Specifies not to shrink the input class files. By default, shrinking is + applied; all classes and class members are removed, except for the ones + listed by the various
+ +-keep
options, and the ones on which + they depend, directly or indirectly. A shrinking step is also applied + after each optimization step, since some optimizations may open the + possibility to remove more classes and class members.- + +
-printusage
+ [filename]- Specifies to list dead code of the input class files. The list is printed + to the standard output or to the given file. For example, you can list the unused code of an application. + Only applicable when shrinking.
+ +- + +
-whyareyoukeeping
+ class_specification- Specifies to print details on why the given classes and class members are + being kept in the shrinking step. This can be useful if you are wondering + why some given element is present in the output. In general, there can be + many different reasons. This option prints the shortest chain of methods + to a specified seed or entry point, for each specified class and class + member. In the current implementation, the shortest chain that is + printed out may sometimes contain circular deductions -- these do not + reflect the actual shrinking process. If the
+ +-verbose
option if specified, the traces + include full field and method signatures. Only applicable when + shrinking.+ +
Optimization Options
+ ++
+- + +
-dontoptimize
- Specifies not to optimize the input class files. By default, optimization + is enabled; all methods are optimized at a bytecode level.
+ +- + +
-optimizations
+ optimization_filter- Specifies the optimizations to be enabled and disabled, at a more + fine-grained level. Only applicable when optimizing. This is an expert + option.
+ +- + +
-optimizationpasses
n- Specifies the number of optimization passes to be performed. By default, a + single pass is performed. Multiple passes may result in further + improvements. If no improvements are found after an optimization pass, the + optimization is ended. Only applicable when optimizing.
+ +- + +
-assumenosideeffects
+ class_specification- Specifies methods that don't have any side effects (other than maybe + returning a value). In the optimization step, ProGuard will then remove + calls to such methods, if it can determine that the return values aren't + used. ProGuard will analyze your program code to find such methods + automatically. It will not analyze library code, for which this option can + therefore be useful. For example, you could specify the method +
+ +System.currentTimeMillis()
, so that any idle calls to it will + be removed. With some care, you can also use the option to + remove logging code. Note that + ProGuard applies the option to the entire hierarchy of the specified + methods. Only applicable when optimizing. In general, making assumptions + can be dangerous; you can easily break the processed code. Only use + this option if you know what you're doing!- + +
-allowaccessmodification
- Specifies that the access modifiers of classes and class members may be + broadened during processing. This can improve the results of the + optimization step. For instance, when inlining a public getter, it may be + necessary to make the accessed field public too. Although Java's binary + compatibility specifications formally do not require this (cfr. The Java Language Specification, Second Edition, Section 13.4.6), some virtual machines would have problems with the + processed code otherwise. Only applicable when optimizing (and when + obfuscating with the
+ +-repackageclasses
option). ++ Counter-indication: you probably shouldn't use this option when + processing code that is to be used as a library, since classes and class + members that weren't designed to be public in the API may become + public.
- + +
-mergeinterfacesaggressively
- Specifies that interfaces may be merged, even if their implementing + classes don't implement all interface methods. This can reduce the size of + the output by reducing the total number of classes. Note that Java's + binary compatibility specifications allow such constructs (cfr. The Java Language Specification, Second Edition, Section 13.5.3), even if they are not allowed in the Java language + (cfr. The Java Language Specification, Second Edition, Section 8.1.4). Only applicable when optimizing. +
+ ++ Counter-indication: setting this option can reduce the performance + of the processed code on some JVMs, since advanced just-in-time + compilation tends to favor more interfaces with fewer implementing + classes. Worse, some JVMs may not be able to handle the resulting code. + Notably: +
+
- Sun's JRE 1.3 may throw an
+InternalError
when + encountering more than 256 Miranda methods (interface methods + without implementations) in a class.+ +
Obfuscation Options
+ ++
+- + +
-dontobfuscate
- Specifies not to obfuscate the input class files. By default, obfuscation + is applied; classes and class members receive new short random names, + except for the ones listed by the various
+ +-keep
options. + Internal attributes that are useful for debugging, such as source files + names, variable names, and line numbers are removed.- + +
-printmapping
+ [filename]- Specifies to print the mapping from old names to new names for classes and + class members that have been renamed. The mapping is printed to the + standard output or to the given file. For example, it is required for + subsequent incremental + obfuscation, or if you ever want to make sense again of obfuscated stack traces. Only + applicable when obfuscating.
+ +- + +
-applymapping
+ filename- Specifies to reuse the given name mapping that was printed out in a + previous obfuscation run of ProGuard. Classes and class members that are + listed in the mapping file receive the names specified along with them. + Classes and class members that are not mentioned receive new names. The + mapping may refer to input classes as well as library classes. This option + can be useful for incremental + obfuscation, i.e. processing add-ons or small patches to an existing + piece of code. If the structure of the code changes fundamentally, + ProGuard may print out warnings that applying a mapping is causing + conflicts. You may be able to reduce this risk by specifying the option
+ +-useuniqueclassmembernames
+ in both obfuscation runs. Only a single mapping file is allowed. Only + applicable when obfuscating.- + +
-obfuscationdictionary
+ filename- Specifies a text file from which all valid words are used as obfuscated + field and method names. By default, short names like 'a', 'b', etc. are + used as obfuscated names. With an obfuscation dictionary, you can specify + a list of reserved key words, or identifiers with foreign characters, for + instance. White space, punctuation characters, duplicate words, and + comments after a
+ +#
sign are ignored. Note that an + obfuscation dictionary hardly improves the obfuscation. Decent compilers + can automatically replace them, and the effect can fairly simply be undone + by obfuscating again with simpler names. The most useful application is + specifying strings that are typically already present in class files (such + as 'Code'), thus reducing the class file sizes just a little bit more. + Only applicable when obfuscating.- + +
-classobfuscationdictionary
+ filename- Specifies a text file from which all valid words are used as obfuscated + class names. The obfuscation dictionary is similar to the one of the + option
+ +-obfuscationdictionary
. + Only applicable when obfuscating.- + +
-packageobfuscationdictionary
+ filename- Specifies a text file from which all valid words are used as obfuscated + package names. The obfuscation dictionary is similar to the one of the + option
+ +-obfuscationdictionary
. + Only applicable when obfuscating.- + +
-overloadaggressively
- Specifies to apply aggressive overloading while obfuscating. Multiple + fields and methods can then get the same names, as long as their arguments + and return types are different (not just their arguments). This option can + make the processed code even smaller (and less comprehensible). Only + applicable when obfuscating. +
+ ++ Counter-indication: the resulting class files fall within the Java + bytecode specification (cfr. The Java Virtual Machine Specification, Second Edition, first + paragraphs of Section 4.5 and Section 4.6), even though this kind of overloading is not allowed in + the Java language (cfr. The Java Language Specification, Second Edition, Section 8.3 and Section 8.4.7). Still, some tools have problems with it. Notably: +
+
- Sun's JDK 1.2.2
+javac
compiler produces an exception when + compiling with such a library (cfr. Bug #4216736). + You probably shouldn't use this option for processing libraries.- Sun's JRE 1.4 and later fail to serialize objects with overloaded + primitive fields.
+- Sun's JRE 1.5
+pack200
tool reportedly has problems with + overloaded class members.- Google's Dalvik VM can't handle overloaded static fields.
+- + +
-useuniqueclassmembernames
- Specifies to assign the same obfuscated names to class members that have + the same names, and different obfuscated names to class members that have + different names (for each given class member signature). Without the + option, more class members can be mapped to the same short names like 'a', + 'b', etc. The option therefore increases the size of the resulting code + slightly, but it ensures that the saved obfuscation name mapping can + always be respected in subsequent incremental obfuscation steps. +
+ ++ For instance, consider two distinct interfaces containing methods with the + same name and signature. Without this option, these methods may get + different obfuscated names in a first obfuscation step. If a patch is then + added containing a class that implements both interfaces, ProGuard will + have to enforce the same method name for both methods in an incremental + obfuscation step. The original obfuscated code is changed, in order to + keep the resulting code consistent. With this option in the initial + obfuscation step, such renaming will never be necessary. +
+ This option is only applicable when obfuscating. In fact, if you are + planning on performing incremental obfuscation, you probably want to avoid + shrinking and optimization altogether, since these steps could remove or + modify parts of your code that are essential for later additions.
- + +
-dontusemixedcaseclassnames
- Specifies not to generate mixed-case class names while obfuscating. By + default, obfuscated class names can contain a mix of upper-case characters + and lower-case characters. This creates perfectly acceptable and usable + jars. Only if a jar is unpacked on a platform with a case-insensitive + filing system (say, Windows), the unpacking tool may let similarly named + class files overwrite each other. Code that self-destructs when it's + unpacked! Developers who really want to unpack their jars on Windows can + use this option to switch off this behavior. Obfuscated jars will become + slightly larger as a result. Only applicable when obfuscating.
+ +- + +
-keeppackagenames
+ [package_filter]- Specifies not to obfuscate the given package names. The optional filter is + a comma-separated list of package names. Package names can contain + ?, *, and ** wildcards, and they can be preceded by + the ! negator. Only applicable when obfuscating.
+ +- + +
-flattenpackagehierarchy
+ [package_name]- Specifies to repackage all packages that are renamed, by moving them into + the single given parent package. Without argument or with an empty string + (''), the packages are moved into the root package. This option is one + example of further obfuscating package + names. It can make the processed code smaller and less comprehensible. + Only applicable when obfuscating.
+ +- + +
-repackageclasses
+ [package_name]- Specifies to repackage all class files that are renamed, by moving them + into the single given package. Without argument or with an empty string + (''), the package is removed completely. This option option overrides the +
+ +-flattenpackagehierarchy
+ option. It is another example of further obfuscating package names. It can + make the processed code even smaller and less comprehensible. Its + deprecated name is-defaultpackage
. Only applicable when + obfuscating. ++ Counter-indication: classes that look for resource files in their + package directories will no longer work properly if they are moved + elsewhere. When in doubt, just leave the packaging untouched by not using + this option.
- + +
-keepattributes
+ [attribute_filter]- Specifies any optional attributes to be preserved. The attributes can be + specified with one or more
+ +-keepattributes
directives. The + optional filter is a comma-separated list of attribute names. Attribute + names can contain ?, *, and ** wildcards, and they + can be preceded by the ! negator. Typical optional attributes are +Exceptions
,Signature
,Deprecated
, +SourceFile
,SourceDir
, +LineNumberTable
,LocalVariableTable
, +LocalVariableTypeTable
,Synthetic
, +EnclosingMethod
,RuntimeVisibleAnnotations
, +RuntimeInvisibleAnnotations
, +RuntimeVisibleParameterAnnotations
, +RuntimeInvisibleParameterAnnotations
, and +AnnotationDefault
. TheInnerClasses
attribute + name can be specified as well, referring to the source name part of this + attribute. For example, you should at least keep the +Exceptions
,InnerClasses
, and +Signature
attributes + when processing a library. You should + also keep theSourceFile
and +LineNumberTable
attributes + for producing useful obfuscated stack + traces. Finally, you may want + to keep annotations if your code + depends on them. Only applicable when obfuscating.- + +
-keepparameternames
- Specifies to keep the parameter names and types of methods that are kept. + This option actually keeps trimmed versions of the debugging attributes +
+ +LocalVariableTable
and +LocalVariableTypeTable
. It can be useful when + processing a library. Some IDEs can + use the information to assist developers who use the library, for example + with tool tips or autocompletion. Only applicable when obfuscating.- + +
-renamesourcefileattribute
+ [string]- Specifies a constant string to be put in the
+ +SourceFile
+ attributes (andSourceDir
attributes) of the class files. + Note that the attribute has to be present to start with, so it also has to + be preserved explicitly using the-keepattributes
directive. + For example, you may want to have your processed libraries and + applications produce useful obfuscated + stack traces. Only applicable when obfuscating.- + +
-adaptclassstrings
+ [class_filter]- Specifies that string constants that correspond to class names should be + obfuscated as well. Without a filter, all string constants that correspond + to class names are adapted. With a filter, only string constants in + classes that match the filter are adapted. For example, if your code + contains a large number of hard-coded strings that refer to classes, and + you prefer not to keep their names, you may want to use this option. + Primarily applicable when obfuscating, although corresponding classes are + automatically kept in the shrinking step too.
+ +- + +
-adaptresourcefilenames
+ [file_filter]- Specifies the resource files to be renamed, based on the obfuscated names + of the corresponding class files (if any). Without a filter, all resource + files that correspond to class files are renamed. With a filter, only + matching files are renamed. For example, see processing resource files. Only + applicable when obfuscating.
+ +- + +
-adaptresourcefilecontents
+ [file_filter]- Specifies the resource files whose contents are to be updated. Any class + names mentioned in the resource files are renamed, based on the obfuscated + names of the corresponding classes (if any). Without a filter, the + contents of all resource files updated. With a filter, only matching files + are updated. The resource files are parsed and written using the + platform's default character set. You can change this default character set + by setting the environment variable
+ +LANG
or the Java system + propertyfile.encoding
. For an example, + see processing resource files. + Only applicable when obfuscating.+ +
Preverification Options
+ ++
+- + +
-dontpreverify
- Specifies not to preverify the processed class files. By default, class + files are preverified if they are targeted at Java Micro Edition or at + Java 6 or higher. For Java Micro Edition, preverification is required, so + you will need to run an external preverifier on the processed code if you + specify this option. For Java 6, preverification is optional, but as of + Java 7, it is required. Only when eventually targeting Android, it is not + necessary, so you can then switch it off to reduce the processing time a + bit.
+ +- + +
-microedition
- Specifies that the processed class files are targeted at Java Micro + Edition. The preverifier will then add the appropriate StackMap + attributes, which are different from the default StackMapTable attributes + for Java Standard Edition. For example, you will need this option if you + are processing midlets.
+ ++ +
General Options
+ ++
+- + +
-verbose
- Specifies to write out some more information during processing. If the + program terminates with an exception, this option will print out the entire + stack trace, instead of just the exception message.
+ +- + +
-dontnote
+ [class_filter]- Specifies not to print notes about potential mistakes or omissions in the + configuration, like typos in class names, or like missing options that + might be useful. The optional filter is a regular expression; ProGuard + doesn't print notes about classes with matching names.
+ +- + +
-dontwarn
+ [class_filter]- Specifies not to warn about unresolved references and other important + problems at all. The optional filter is a regular expression; ProGuard + doesn't print warnings about classes with matching names. Ignoring + warnings can be dangerous. For instance, if the unresolved classes or + class members are indeed required for processing, the processed code will + not function properly. Only use this option if you know what you're + doing!
+ +- + +
-ignorewarnings
- Specifies to print any warnings about unresolved references and other + important problems, but to continue processing in any case. Ignoring + warnings can be dangerous. For instance, if the unresolved classes or + class members are indeed required for processing, the processed code will + not function properly. Only use this option if you know what you're + doing!
+ +- + +
-printconfiguration
+ [filename]- Specifies to write out the entire configuration that has been parsed, with + included files and replaced variables. The structure is printed to the + standard output or to the given file. This can sometimes be useful for + debugging configurations, or for converting XML configurations into a more + readable format.
+ +- + +
-dump
+ [filename]- Specifies to write out the internal structure of the class files, after + any processing. The structure is printed to the standard output or to the + given file. For example, you may want to write out the contents of a given jar + file, without processing it at all.
+ ++ +
Class Paths
+ +ProGuard accepts a generalization of class paths to specify input files and +output files. A class path consists of entries, separated by the traditional +path separator (e.g. ':' on Unix, or ';' on Windows platforms). +The order of the entries determines their priorities, in case of duplicates. ++Each input entry can be: +
+
+- A class file or resource file,
+- A jar file, containing any of the above,
+- A war file, containing any of the above,
+- An ear file, containing any of the above,
+- A zip file, containing any of the above,
+- A directory (structure), containing any of the above.
++The paths of directly specified class files and resource files is ignored, so +class files should generally be part of a jar file, a war file, an ear file, a +zip file, or a directory. In addition, the paths of class files should not have +any additional directory prefixes inside the archives or directories. + +
+Each output entry can be: +
+
+- A jar file, in which all processed class files and resource files will be + collected.
+- A war file, in which any and all of the above will be collected,
+- An ear file, in which any and all of the above will be collected,
+- A zip file, in which any and all of the above will be collected,
+- A directory, in which any and all of the above will be collected.
++When writing output entries, ProGuard will generally package the results in a +sensible way, reconstructing the input entries as much as required. Writing +everything to an output directory is the most straightforward option: the +output directory will contain a complete reconstruction of the input entries. +The packaging can be almost arbitrarily complex though: you could process an +entire application, packaged in a zip file along with its documentation, +writing it out as a zip file again. The Examples section shows a few ways +to restructure output archives. +
+Files and directories can be specified as discussed in the section on file names below. +
+In addition, ProGuard provides the possibility to filter the class path +entries and their contents, based on their full relative file names. Each +class path entry can be followed by up to 5 types of file filters between parentheses, separated by +semi-colons: +
+
+- A filter for all zip names that are encountered,
+- A filter for all ear names that are encountered,
+- A filter for all war names that are encountered,
+- A filter for all jar names that are encountered,
+- A filter for all class file names and resource file names that are + encountered.
++If fewer than 5 filters are specified, they are assumed to be the latter +filters. Any empty filters are ignored. More formally, a filtered class path +entry looks like this: +
+classpathentry([[[[zipfilter;]earfilter;]warfilter;]jarfilter;]filefilter) +++Square brackets "[]" mean that their contents are optional. +
+For example, "
rt.jar(java/**.class,javax/**.class)
" matches all +class files in thejava
andjavax
directories inside +thert
jar. ++For example, "
input.jar(!**.gif,images/**)
" matches all files in +theimages
directory inside theinput
jar, except +gif files. ++The different filters are applied to all corresponding file types, irrespective +of their nesting levels in the input; they are orthogonal. +
+For example, +"
input.war(lib/**.jar,support/**.jar;**.class,**.gif)
" only +considers jar files in thelib
andsupport
+directories in theinput
war, not any other jar files. It then +matches all class files and gif files that are encountered. ++The filters allow for an almost infinite number of packaging and repackaging +possibilities. The Examples section provides a few more examples +for filtering input and output. +
+ +
File Names
+ +ProGuard accepts absolute paths and relative paths for the various file names +and directory names. A relative path is interpreted as follows: ++
+- relative to the base directory, if set, or otherwise
+- relative to the configuration file in which it is specified, if any, or + otherwise
+- relative to the working directory.
++The names can contain Java system properties (or Ant properties, when using +Ant), delimited by angular brackets, '<' and '>'. The +properties are automatically replaced by their corresponding values. +
+For example,
<java.home>/lib/rt.jar
is automatically +expanded to something like/usr/local/java/jdk/jre/lib/rt.jar
. +Similarly,<user.home>
is expanded to the user's home +directory, and<user.dir>
is expanded to the current +working directory. ++Names with special characters like spaces and parentheses must be quoted with +single or double quotes. Each file name in a list of names has to be quoted +individually. Note that the quotes themselves may need to be escaped when used +on the command line, to avoid them being gobbled by the shell. +
+For example, on the command line, you could use an option like
'-injars +"my program.jar":"/your directory/your program.jar"'
. ++ +
File Filters
+ +Like general filters, a file filter is a +comma-separated list of file names that can contain wildcards. Only files with +matching file names are read (in the case of input jars), or written (in the +case of output jars). The following wildcards are supported: + ++
+ +For example, "+ + ?
matches any single character in a file name. + + *
matches any part of a filename not containing the directory + separator. + + **
matches any part of a filename, possibly containing any number of + directory separators. java/**.class,javax/**.class
" matches all +class files in thejava
andjavax
. ++ +Furthermore, a file name can be preceded by an exclamation mark '!' to +exclude the file name from further attempts to match with +subsequent file names. +
+For example, "
!**.gif,images/**
" matches all files in the +images
directory, except gif files. ++The Examples section provides a few more examples for filtering input and output. + +
Filters
+ +ProGuard offers options with filters for many different aspects of the +configuration: names of files, directories, classes, packages, attributes, +optimizations, etc. ++A filter is a list of comma-separated names that can contain wildcards. Only +names that match an item on the list pass the filter. The supported wildcards +depend on the type of names for which the filter is being used, but the +following wildcards are typical: + +
+
+ +For example, "+ + ?
matches any single character in a name. + + *
matches any part of a name not containing the package separator or + directory separator. + + **
matches any part of a name, possibly containing any number of + package separators or directory separators. foo,*bar
" matches the namefoo
and +all names ending withbar
. ++ +Furthermore, a name can be preceded by a negating exclamation mark '!' +to exclude the name from further attempts to match +with subsequent names. So, if a name matches an item in the filter, it +is accepted or rejected right away, depending on whether the item has a +negator. If the name doesn't match the item, it is tested against the next +item, and so on. It if doesn't match any items, it is accepted or rejected, +depending on the whether the last item has a negator or not. +
+For example, "
!foobar,*bar
" matches all names ending with +bar
, exceptfoobar
. ++ +
Overview of
+ +The variousKeep
Options-keep
options for shrinking and obfuscation may seem +a bit confusing at first, but there's actually a pattern behind them. The +following table summarizes how they are related: ++ +
+ +
++ + +Keep +From being removed or renamed +From being renamed ++ + +Classes and class members ++ -keep
+ -keepnames
+ + +Class members only ++ -keepclassmembers
+ -keepclassmembernames
+ + +Classes and class members, if class members present ++ -keepclasseswithmembers
+ -keepclasseswithmembernames
+ +Each of these
-keep
options is of course followed by a +specification of the classes and class +members (fields and methods) to which it should be applied. ++If you're not sure which option you need, you should probably simply use +
-keep
. It will make sure the specified classes and class members +are not removed in the shrinking step, and not renamed in the obfuscation step. ++ +
+
+- If you specify a class, without class members, ProGuard only preserves the + class and its parameterless constructor as entry points. It may + still remove, optimize, or obfuscate its other class members.
+- If you specify a method, ProGuard only preserves the method as an entry + point. Its code may still be optimized and adapted.
++ +
Keep Option Modifiers
+ ++
+- + +
allowshrinking
- Specifies that the entry points specified in the -keep + option may be shrunk, even if they have to be preserved otherwise. That + is, the entry points may be removed in the shrinking step, but if they are + necessary after all, they may not be optimized or obfuscated.
+ +- + +
allowoptimization
- Specifies that the entry points specified in the -keep + option may be optimized, even if they have to be preserved otherwise. That + is, the entry points may be altered in the optimization step, but they may + not be removed or obfuscated. This modifier is only useful for achieving + unusual requirements.
+ +- + +
allowobfuscation
- Specifies that the entry points specified in the -keep + option may be obfuscated, even if they have to be preserved otherwise. That + is, the entry points may be renamed in the obfuscation step, but they may + not be removed or optimized. This modifier is only useful for achieving + unusual requirements.
+ ++ +
Class Specifications
+ +A class specification is a template of classes and class members (fields and +methods). It is used in the various-keep
options and in the +-assumenosideeffects
option. The corresponding option is only +applied to classes and class members that match the template. ++The template was designed to look very Java-like, with some extensions for +wildcards. To get a feel for the syntax, you should probably look at the examples, but this is an attempt at a complete formal +definition: +
+ +
+[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname + [extends|implements [@annotationtype] classname] +[{ + [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> | + (fieldtype fieldname); + [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> | + <init>(argumenttype,...) | + classname(argumenttype,...) | + (returntype methodname(argumenttype,...)); + [@annotationtype] [[!]public|private|protected|static ... ] *; + ... +}] +++Square brackets "[]" mean that their contents are optional. Ellipsis dots +"..." mean that any number of the preceding items may be specified. A vertical +bar "|" delimits two alternatives. Non-bold parentheses "()" just group parts +of the specification that belong together. The indentation tries to clarify +the intended meaning, but white-space is irrelevant in actual configuration +files. +
+
+ +
+ +- The
+ +class
keyword refers to any interface or class. + Theinterface
keyword restricts matches to interface + classes. Theenum
keyword restricts matches to + enumeration classes. Preceding theinterface
or +enum
keywords by a!
restricts + matches to classes that are not interfaces or enumerations, + respectively.- Every classname must be fully qualified, e.g. +
+ +java.lang.String
. Inner classes are separated by a dollar sign + "$
", e.g.java.lang.Thread$State
. Class names + may be specified as regular + expressions containing the following wildcards: + ++ +
+ + For additional flexibility, class names can actually be comma-separated + lists of class names, with optional+ + + + ?
matches any single character in a class name, but not the package + separator. For example, " mypackage.Test?
" matches + "mypackage.Test1
" and "mypackage.Test2
", but not + "mypackage.Test12
".+ + + + *
matches any part of a class name not containing the package separator. For + example, " mypackage.*Test*
" matches + "mypackage.Test
" and + "mypackage.YourTestApplication
", but not + "mypackage.mysubpackage.MyTest
". Or, more generally, + "mypackage.*
" matches all classes in + "mypackage
", but not in its subpackages.+ + + + **
matches any part of a class name, possibly containing any number of + package separators. For example, " **.Test
" matches all +Test
classes in all packages except the root package. Or, + "mypackage.**
" matches all classes in + "mypackage
" and in its subpackages.!
negators, just + like file name filters. This notation doesn't look very Java-like, so it + should be used with moderation. ++ For convenience and for backward compatibility, the class name +
*
refers to any class, irrespective of its package.- The
+ +extends
andimplements
+ specifications are typically used to restrict classes with wildcards. They + are currently equivalent, specifying that only classes extending or + implementing the given class qualify. Note that the given class itself is + not included in this set. If required, it should be specified in a + separate option.- The
+ +@
specifications can be used to restrict classes + and class members to the ones that are annotated with the specified + annotation types. An annotationtype is specified just like a + classname.- Fields and methods are specified much like in Java, except that method + argument lists don't contain argument names (just like in other tools + like
+ +javadoc
andjavap
). The specifications can + also contain the following catch-all wildcards: + ++ +
+ + Note that the above wildcards don't have return types. Only the ++ + + <init>
matches any constructor. + + + <fields>
matches any field. + + + <methods>
matches any method. + + + *
matches any field or method. <init>
wildcard has an argument list. ++ + Fields and methods may also be specified using regular expressions. Names + can contain the following wildcards: + +
+
+ + Types in descriptors can contain the following wildcards: + ++ + ?
matches any single character in a method name. + + *
matches any part of a method name. +
+ + Note that the+ + %
matches any primitive type (" boolean
", "int
", + etc, but not "void
").+ + ?
matches any single character in a class name. + + *
matches any part of a class name not containing the package separator. + + **
matches any part of a class name, possibly containing any number of + package separators. + + ***
matches any type (primitive or non-primitive, array or + non-array). + + + ...
matches any number of arguments of any type. ?
,*
, and**
+ wildcards will never match primitive types. Furthermore, only the +***
wildcards will match array types of any dimension. For + example, "** get*()
" matches "java.lang.Object + getObject()
", but not "float getFloat()
", nor + "java.lang.Object[] getObjects()
".- Constructors can also be specified using their short class names (without + package) or using their full class names. As in the Java language, the + constructor specification has an argument list, but no return type.
+ +- The class access modifiers and class member access modifiers are typically + used to restrict wildcarded classes and class members. They specify that + the corresponding access flags have to be set for the member to match. A + preceding
+ +!
specifies that the corresponding access + flag should be unset. ++ Combining multiple flags is allowed (e.g.
public static
). It + means that both access flags have to be set (e.g.public
+ andstatic
), except when they are conflicting, in + which case at least one of them has to be set (e.g. at least +public
+ orprotected
). ++ ProGuard supports the additional modifiers
synthetic
, +bridge
, andvarargs
, which may be + set by compilers.
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/manual/wtk.html b/docs/manual/wtk.html new file mode 100644 index 000000000..a7ea0b81b --- /dev/null +++ b/docs/manual/wtk.html @@ -0,0 +1,70 @@ + + + + + + +ProGuard JME Wireless Toolkit Integration + + + + +JME Wireless Toolkit Integration
+ +ProGuard can be seamlessly integrated in Oracle's Wireless Toolkit (WTK) +for Java Micro Edition (JME). ++ +The WTK already comes with a plug-in for ProGuard. Alternatively, ProGuard +offers its own plug-in. This latter implementation is recommended, as it more +up to date and it solves some problems. It is also somewhat more efficient, +invoking the ProGuard engine directly, instead of writing out a configuration +file and running ProGuard in a separate virtual machine. +
+ +In order to integrate this plug-in in the toolkit, you'll have to put the +following lines in the file +{j2mewtk.dir}
/wtklib/Linux/ktools.properties
or +{j2mewtk.dir}\wtklib\Windows\ktools.properties
(whichever is +applicable). ++ +
+obfuscator.runner.class.name: proguard.wtk.ProGuardObfuscator +obfuscator.runner.classpath: /usr/local/java/proguard/lib/proguard.jar +++ +Please make sure the class path is set correctly for your system. +
+ +Once ProGuard has been set up, you can apply it to your projects as part of +the build process. The build process is started from the WTK menu bar: +
+
Project -> Package -> Create Obfuscated Package ++This option will compile, shrink, obfuscate, verify, and install your midlets +for testing. +
+Should you ever need to customize your ProGuard configuration for the JME WTK, +you can adapt the configuration file
proguard/wtk/default.pro
+that's inside theproguard.jar
. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/quality.html b/docs/quality.html new file mode 100644 index 000000000..d9935fc41 --- /dev/null +++ b/docs/quality.html @@ -0,0 +1,56 @@ + + + + + + +ProGuard Quality + + + + +Quality
+ +In order to get a feel for the quality of the ProGuard code, it is run +through a regular automatic build process. This process produces numerous +statistics on the source code, Java lint comments, Java documentation +comments, the Java documentation itself, html lint comments on the Java +documentation, spell checks, compilation results, an output jar, dead code +analysis, a shrunk and obfuscated jar (using ProGuard itself!), test runs with +memory and performance analyses, etc. Most analyses are produced using freely +available tools. The results are poured into a convenient set of web pages +using bash/sed/awk scripts. You're welcome to have a look at an uploaded +snapshot of one of these runs: ++
Automated Code Analysis and Testing Pages (at SourceForge) ++The pages will appear in a new window, which you probably want to view at +full-screen size. +
+ +In addition, ProGuard is tested against a constantly growing test suite +(more than 1500 tests at this time of writing). These small programs contain a +wide range of common and uncommon constructs, in order to detect any regression +problems as soon as possible. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + diff --git a/docs/results.html b/docs/results.html new file mode 100644 index 000000000..eee8aa6a4 --- /dev/null +++ b/docs/results.html @@ -0,0 +1,169 @@ + + + + + + +ProGuard Results + + + + +Results
+ +ProGuard successfully processes any Java bytecode, ranging from small +midlets to entire run-time libraries. It primarily reduces the size of the +processed code, with some potential increase in efficiency as an added bonus. +The improvements obviously depend on the original code. The table below +presents some typical results: ++ +
+ +
++ + +Input Program +Original size +After shrinking +After optim. +After obfusc. +Total reduction +Time +Memory usage ++ + +Worm, a sample midlet from Oracle's JME +10.3 K +9.8 K +9.6 K +8.5 K +18 % +2 s +19 M ++ + +Javadocking, a docking library +290 K +281 K +270 K +201 K +30 % +12 s +32 M ++ + +ProGuard itself +648 K +579 K +557 K +348 K +46 % +28 s +66 M ++ + +JDepend, a Java quality metrics tool +57 K +36 K +33 K +28 K +51 % +6 s +24 M ++ + +the run-time classes from Oracle's Java 6 +53 M +23 M +22 M +18 M +66 % +16 min +270 M ++ + +Tomcat, the Apache servlet container +1.1 M +466 K +426 K +295 K +74 % +17 s +44 M ++ + +JavaNCSS, a Java source metrics tool +632 K +242 K +212 K +152 K +75 % +20 s +36 M ++ + +Ant, the Apache build tool +2.4 M +401 K +325 K +242 K +90 % +23 s +61 M ++Results were measured with ProGuard 4.0 on a 2.6 GHz Pentium 4 with 512 MB +of memory, using Sun JDK 1.5.0 in Fedora Core 3 Linux. All of this technology +and software has evolved since, but the gist of the results remains the same. +
+The program sizes include companion libraries. The shrinking step produces the +best results for programs that use only small parts of their libraries. The +obfuscation step can significantly shrink large programs even further, since +the identifiers of their many internal references can be replaced by short +identifiers. +
+The Java 6 run-time classes are the most complex example. The classes perform +a lot of introspection, interacting with the native code of the virtual +machine. The 1500+ lines of configuration were largely composed by automated +analysis, complemented by a great deal of trial and error. The configuration +is probably not complete, but the resulting library successfully serves as a +run-time environment for running applications like ProGuard and the ProGuard +GUI. +
+For small inputs, timings are governed by the reading and parsing of the jars. +For large inputs, the optimization step becomes more important. For instance, +processing the Java 6 run-time classes without optimization only takes 2 +minutes. +
+Memory usage (the amount of physical memory used by ProGuard while processing) +is governed by the basic java virtual machine and by the total size of the +library jars and program jars. + +
+ + +Copyright © 2002-2013 +Eric Lafortune. + + + + diff --git a/docs/saikoalogo.png b/docs/saikoalogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5b34172157cc0f0efd05aefc4489cf4803048cb6 GIT binary patch literal 2901 zcmV-b3##;qP)Px=4@pEpR9Hvln0atr^>xQT=id7^J-w&pNwOBpmiO33mTlP%P#X+|0XJ=E2AUR6 zO`DLJwrM6AYM3(43{0R*iqlf2*-C(+1Ej>11j-hc5Xj;UWDBq@TQadMS++K7v!wU* zmU~bCxbHr_Cwc4oM|)=8%=_N6{Lb&(v;6K)HviR&uOqqzmlOn41&>7ZQdm{RFobZ> zhiQnaGR+5t|4pn}oO|>i)c>zz5hP *ij_tH}!bWm^}8{k>9o4 z*vt9VE|XLhzh$y!Q6*)Oz@^0hUr@j@)n^%EF+0V{VV9$qgH@G8Dnl6o)%+F$Dk1{l zILglsp3 Sg^j z43V+Pls@=u3rD+$x$lqH%jTv!^_d2v6DbZHACRZsJgP(Irt(Y{G^+yasEU#G@As~n z&y~yP$ikYa>$nI-0ZT%DGbiu5QZO?_)y-?ekOKQ6g6*gnGQD0l;IsU33&Z8-@0S_= zS^yMI{Q~U0)nwWxk<8#Ynhml`B0@4{OTceoJNa>+rb8!& _M-Y5bNcbroUOEULs1@q$J;;A5)DA?P >>HQi@hQ?7hiH+X z<@3vAZnk37OUgpZVT=5p>QWvS3_&LoX<1Mc<;J!3#G*m99VG81sqLr~2Yr+k2OzKK zdi=C)i|r`c!9Hs}zhz2QX_4owzTe(2cR#j=aL^*?H#L#8MS#y<-N4;{uqJ2!?SnnM z@T=eG1An?fme-f%^vN$V&|U8xm+!xFm^-(uV8f^8C?Fr7ILpJkS~<}>rsdI~43ACG zP!r|rTbuQYhFH$O@4kFkfBJrxM2q}bra>Z=(W=srY`<+an;L7$R>uY6=VfqVQ_W#j zC7E(qGPhKBY+Z-nGUywQdq#5_j;aQHCZ<`a@6qDA5?wmCgzvt52n04>QKNOSuven9 z R=xfDrEI%l82|&Laed&~7ED8Ua{Kkv#=?4LXp*l#wV%IvwuSG1?OH911j*PA zS1zySrgiglNnHuypvBO+B;S1QfbM+0l@;^LiA966{LjZ;fF<{MMn;cMrS!U{I*EpS zeBtljp?5g0k&sV90Z$c8r5&k_g?aSL8>x+1>Xk5n |hE06x 1+tzdE z-~U`++1Dj^+_(%!mCs()P!Nxja6oTbKTmc%xtFu&riev@1^eZ^8JwR0NC7rQ7@JJt z_Zcj%EupG3#8k?rdtd_75KL1@rfiaFyU>hhExXjF##&a)FXzpcZVq)0(LWNWZ+MbN ze*7U%ztzrzU-&fZmsRDm`cUT(Zy!8G+sP4<8JmplFglSWIQ?SJORC_v41Rg&3=chb zfUVar<*r+s3S`=QMp;r $rAs~1%e4*KZm83Dj=nZ%PB-fivSSBHBU7)y|` zm5D@(NXYNbqf5|5y%iB6MSk9C?O|m@IrrbOfmGT?M0ou5BfN942cKzx&)w9l1I`SJ zMT2a;erXO5jwX1crJL`(^f6Dq(MIEfa)N$~pZxka?A+DL;<^%=msC<74PuD!!*|-r z*cabaQNW_DYlN1LLC%gP*xXbLOb0QYahOP?DUSrao}D9Ar6lYpnRbUoJelF%$M>+m zeSm9M)v|U`1+^7nj&+Z4;> fdw-rqKHWUXq< I@A6bGXfGdEmWJ4N!!l_ 3b&_ zzt7#zzwPei{f+^-=ksg0ZPTKh*uJBEJoB@T+zI7k`!z(|Gj86m00SBh_(-O0eto!? zUwm|04|EI?4f`n$`DP3lfax E&nQQ_hI9OU;f(F*;8=q4Xpl&epRvi5b`Okm zT~i(5pf4wXE}kNpc5ts63a9|br!v~OFvb^eUd{u5vL4eAz2^se=pCK}+y=O)wuJVc z5qgK?0J$^lvF;Jh#Z$Vl#%&$#JtI^`Lwdv7xdrQuj3*15eqjg-fVJcH=KN`XQF2uA z83wBsR`A}3r|CI6LC|l_DzzDJltZ0EJn-xXeCc;qa8vU JtukQt#%2AeE2Pc@kE-k;(*+BYZJF-OR%yu zBwzXcRqTBJAh+E2I%Sc7_$`B#4KZrU!x(wHu}p)Y-zX^2fX@`u5NzAQGz~sgUnYP1 zrK|Ys$M^89e{JRdZR@4JvX~uPo7uVRAh$pCmdq(DqJK0_w8+nn+nc4jya<3>u4-U! zTc14g!iPNZ`Voo(KI$sMGOsGanX{9~bZGLauwShE@-Efs_zE+Q8Rx@-NWf>}vkU|@ znYN|2BFwkHat+mGMd#I5l-5tqa^lQ69h*#wqfi?5vu;_HE~t*ql7IhLKL?HvVwr}n zS{RcJ%jVGf$snPCrOW4)2|&-_1g8ckv~fX9ysT~gWKc~*WYxlo0((cghUx4*$8W8y z(XvQD08R}~@QaU5>&SRg%Ax_TX{=>lRiwcG_*6!J`azfU4o^}Z3G&-(=4vG5lih87 zT)m>2aL{+Y{nCDFgnOUZE3$d}i|Re(G6U@4>}1wd+LpSCV!rp)Yp5s*UAF%JVaz9| z$GGPQyTt;gfM8ytxtH$K;upl;6g5rJiA0*G-)^TY5|C7;pfS2HP2C=@?v12+EW>c` zOJ>SDj^@7eMMMn|_c~L^UG{kP3=tJ^ci=cGfacAWoIL T9V0000{RZ(VUX0EEP%*@RH|NsC0|NsC0EC2ui0P_NQ z0ssU4Si0O^;>k&?y*TU5yZ>M)j$~<`XsWJk>%L?JJMwJbc&_h!@BhG{aHy$uWQ3%0 z$z(>F(5Q4uty-_xtai)odcWYXcuX#v&*-#z&2GE7PdE}@c-!yzynfH``~QG}f`e&s zTLN>3b%czKj*pO$l9QB`mP>|Ohzd%Go}ZwhqNAjxrl+W>s;jK6uCK7Mva__cwzs&s zy1Tr+zQ4f1pq+_E7RD9G6v{-+&d<=%($mz{)*Q?dhMS87nN;6X;Zoz5=I7|?>g(+7 zeC1Hv#obl#P4-Uo?)&`x{{H|20>X!>8@EpS#3dxRFbY9|5F=gz0H6xRi;^y4#G?MO zVi<}NLyC;I$di*e@;D`VxYFP#gjiUPoJq3@$R!>h-6XJ+%Fdo$fYuz^59P{ENlLm@ z>8&A2q)iMuy*HJp)pHt?fXvEsqgE&$xpuwzvm)8BX3+|rQg& ^aqQyL z<_sD13v=Z>C#(xXWpen6Ow_pfWTso0N!YKGIa4048MG4NHcRsceRgwB%gaOOp3W$f zK6)u@&nCP&YHQk0sf!o%8Lm*X$G@KE>KwYlthZoj|<6Fa-CuEIGf>Bt3FE#~Og5Us% z;CBi(sihh06)7KmL-yDqk3oj$6Op1lC>e-AK4<2ZaDK5D0d;iqmx@#> &mkjG2~dhoOR+ zs;WDqPWdQ9l194fthClTYpbq>0)Z;KrqU}azX~Jlu*4Q??6Jru{;TY=%r@&RFTt7; zYy$!~X6?1uW~=SC+;;2jx8Q~=?zrTZYwo$|rmOC{?6&LfyYR*<@4WQVJ3s*U=8NyX z`VKGvpDWcX@W2EYZ1BMdC#>+o3^(lX!wvh(@5KG$yOco?XRPtY9Cz&T#~_C+^2p{^ zY%;(9x*9Oa<0`=N%P_|*^UO5YY_qizpKS8QoyfcZw=REM0K`MzY;Mp%8~rZQN?*iu z(@;mft J<1bJaVm?2Xf8 zuMKq3Kf|jx-W2^Ex6*GLocGLy6F&IjXH#wR)!q~Xc;I~gyWF?dmosg7(0z-I_t2Sd zuC3sXdH#9coFm;exu#RDdF7*n{yOCvt^PUYxYK@m?XcgTIPaIcZg%S14o`dV#P1F~ z?y3)ueDAJ%o$cn%>n=R&sXJeN?p_Cv`O~d`&-nNX&+WLyc2{eC^KB=uck`ud-%<9( zlOA^M_y?Z9^!lG`ywmvOTkHS`KmqcPf2bp1{|;z8112zS3S^-4e%HUyMG$lq+}{Hw zxIhUyaB|Z-Tmdr}L2&(Vfeoyn2sy|?1d{KC1v_8AASa-^>27ws%i;Sr2tw|G(0<}W z+qG7B!2My%0rwkX4!hO99u~2C^ShuDo!CSOCei+S#hYLWdH6&OYS4&A1YZ C7{)gi(|^ZgB_>T-N=Y*FnUriMDUX=UX-;u< zpp+&QC+R{dj tT8;3ba`q9scxr^l?^|?t? z@-dz2WF!h5SwC+^a)qkQihGo3IS+cYaiTD62<2ud z*-27#xzlR!6doTDiAX)NPkcY?Tp+1eP!sNRm#5@qDwpR+Vm?oh-is+uQ75}s4t0rF zj9yQPX~>`EbdPR?DN*wo%b0GjfUg7UB0~sL_Vp2}+S6)4OG?&j)zNV&9o$wusj#sM zkzH<`S6qdrId{#qU3V?3UiW%Zf2DP=dG*`U@cOX8k`t~BGwfa$yUw%Pk%p2hD?bgl zR=QTUtBO_EWS6#CLSELcon@?O%i34S24=LVO|5EI%UYN@R%d^0t!!sY+uGWeU8RjJ z+cGOxc`dS~w+*gvha0iJ{&kft{ x!kubOZD>|5m+Rcf-8 zy5J43c)j&ny2bW?!_;FdgBjK(X4RT#jNa`gm(};~Gl8KcVMLod-v0Vmw${a39$Dx` z1M0V#L`)$kwcEl3ClaD@v?wE=tI7Xb_`=aGZ`}lpO9IDHf4_q+13w&CH3C$d937*G zx#?YHV)(@{rfq;DcUo9p5|u d~Es4I)C(kxea$zTq1V;@T~(_-wq3>B$A*UZ+2x>b-YrZOu{{9P#P zlFMSwv!3JD tj~8G zHD^)0u2TE@*vQsvuFs5IWR8-sgH5)yr@c5}zf;(FW~$AMP3>-b``2Wi;c>wz=#}nR zhl94?^CC^t_2rn`-;TGu=Vfj5$$Fw8g(jSliqNtCbD&1f_Phs9@bZP*me`&sDRo?B z4u1H^8?E9<3r_Kh7x&=TzPC}k{O&pT*qC4bxRE*8LW`UH y1*18#F^gcVn9@lon zRg7Jf+x+IVj5Yp^&)i^;2UF51Mxeigo=|{~d~HaFH_n&dYL%~y$I4UcRJ~fcs{3wl zGPQd5(k(xYdL5}u4?Dr@ZRVAGjN3{VyV}+6^bT_j-f3UE+;L8J-4+(oCdB*P_s(~U zw0+in54_+@T6bX&{_u#G NkEP^b9R=9 ofq4Hr>g21mr^U
2#XaaiH|sjLx*B6M{_n Y>NMMuXgl_m|3TThRn2Rh|gX74L+=zqk zD2sIkhHqGmeE5zP2w`{#j(Ui1uDFXpXO7huSx~oeR^>Y#7et}cUH6lUsu+PACv{Sl zh9;>}Q73*Zd4K 81Z*D+oueX8YrwTM`T<2Ks{eWdnZx43FpseHxPTF#ez ziHCLJ@`nQhmw;H6esz_12Sk&WcWg;MdD)hJ`7&jxYkxVIglRJrSeS^Jm?RUJJO^4` zS!`feSZXtkTA5gnd00azhL(kwkTz+NcZgyMad;_M9o2f61)2pjl@7yuqQ^CtIW{oa zjmAfsbqJZu!I$g_IX^^eA}&DVhS+N#RI*E67j2h?=_jn)?WG5P5*axq8ScFpSxR z&nblTqM0w$iP09Fn5mq*DRXJ2k1?5*9ygqJwVbktowFH}vT2OVRh|C!LYHNiM+Bvl zN_CstXKufxXz+(ajz(Wv*ID87f4 h9om&WX r56Z()B#Hh8&sC{~3=ftMJCjO&5*OVk$q>CDdh1#fS zR*FO>mZAiyRn}g5np9 T0=!t?VPkBY2Q&^Cs$EVFksq6Tr;u5P?CZ0m7 zfS)*sm^Fa)crfRfq0Ly1Z5o~CX^k3sP0&Z9V7hRCnx(8-s@>|IhWe}(*kUmEsM&ga zQ1)(I#;3nIk%DTT?HR6tdak}|d%5|jSc)*yNuTJbf%LeIy*a5~=Z+UOM5f7yP^x+H zD3P#Qt+F~#rst%Q>3>s-MVM%?=t_f2NwA)GoD4aTTAHL|if9p6WW>6B@QRN_)Qe^c zZtgUnHk6T3x{)dAQW5%6&-IeTBa(-fmj`Q MLIU)mw9P+eNRskJBiwkGsD18(iUAtK-X@ z*?Ya`dtmi@zXCj4?YoFG_=^gPi2uuS8CA6oJirjlSExH+ggBD}3Rd#dsY`3N9*MJx znoFS@!6Iy!Xlj>|HNq%7T=}b4iJQVM3^lGhOPBk?G%Q*xT*ElrmNA^eJluCTj4&-6 zm%&T2JzT`}R>B&myux=jIXkT)qq#=xmp2^5YIUyOxt>wny9I2N(5sOEI6H!dlJz7z z73Gx6tE_YyRLGlN1WHv}7hir@fVV5hSv+u4Y^fQTgP>}VL~Kxee2om;$L1TdC8) #hLo$n$o`@A{;n zEWV)ntpd4YuBTkj>BMoSyvm4{#;UVhyMPT!%JK%ue~P~TNXcI+rL7!}_)4#E%E}^( z$m5uhBb&FpT)PwewxD#$*{HwWyRb9Iy$l<$z)Hy4JhVTmkg~YQ(R!mGmCn)ZX@^;~ z>i5RD%xE_|b#B>iAL+(ob!bFclwCZvg+{ipiJ(2JvsA0ZApD8z%+Aw1xzG&6<3+^@ zeRw-es9*We5lzECoXZI_!@ WoeezdY;3gBa9z`o5JN+u?%Q0lC_0%GtfAo{*i1RGPla{koKlr$1<| zLQCBs%girb*oo@g{<4k4OgLcII 66QcE8?Plt+UUH76pOLo38$a^-S=(X zOj@PrE!$R&JxGg`Fol3w7rjb(fcH#O)I-Kr%e<~C&?U;x6z hU1 zoUB^AiOpT$-!j`vY;!5D;z {&~_(Uyh1PpssHOQXLX<*j?*UAmnu-qW_syBee8 z#)qwq4Cc(L-ncmC&%5CquA5(-pn)yc=||Q+{mQ;AMh}>@?lY6R8^;(d*UpQQ(N?c+ z?lDK6MEKhN*RA-+00+zEjM&;(+Gjpzn683)oox-J$o1`y|2E^S{gjQaF;iaW+X$}d z>c@>p+>@Ny_6^+CykDp-grF?S#i-+{Ounh!wqjo1#~i6u)!*B^+wa`l-}vP}9n1<| z%i)cR2|lx&sNCri%AFkS8?)-eD(aIy)Y#qH@tW(X+Jg#9*Mv>ct-h_~je4hw=G-3U zbZK|63*S44?56#Ump;o$UF)Zw$J%PKt~$=|`ri#nZY}NQZ9ebu`Lg!@;qu(UK&jwe zg|-`+@m5vPK}(dkd*K+~&n&uBDB86HZSq^Ilw5A*T?XY2e{t><@olN*FHgO2ZkB{e z^ELh-W{*C1JihaGeDi_{^hB>(Jzw-lKSv?0UCpKQNzd*18-TY;NDck;R!>Jlzo{Wh z=2zeK^d9pG$4r4 -B1{EzSDC3Pxg67U>tb_H@to!#> K?h1V6lllm74w z#^A@_;b%cv9mXVC@MB++A-?|jMSg`&?GvxWbc{yxub) B$e+) z-7xPJRDDxvo@lDBZ0o*oEYEa}4nvUdde099f>0oE2nm7+!$MJBI*q0?I;}#b)GLaa z *eX-D--QM5e;o>nkpyoS4Lq+LG8zdtk$#ccX{@Aa>CA6nt z@fYx}DX6U)2(X?%G|YYp6ER{*zk?3{L0lnGo4tS-89r zZ%!fAzk^Lcde%@!} zF1{K>#OJc}ZIeE_z5Dkm(#HJJHnl1EPVtMi#9qJu{{RLk;D7|SP?}8j)s#em{pr^r z3lA13;e-@cXyJvF$af$*qu6H?fWuK3Vhkf ?4@Ov4XDXFgq=O-@2j!GlW*M4>^Rd 5Y^86=|k_UJ=xcmT<<&(vhJg2quX|g@&dwFYS4vpJValra^KRYG^lHZfIwW zFu18fcd}jQn|U48bsMFCR0qYQn7R|2FMcd{B_WggQsw?{kAhdnZ`d6Mn{yw*^3JI( zK;sdhhvus533Td^q>p&g D{#IJP0Y9kfl~#npI&;c@_n=%l>rNGg3JV z31|I{$PKQ$mTPXJ^DTN`qehL&Syy=$3mH^j-9apbONCpEW!Ls}s}nxKo99jO+N%k_ z$eOG0!Z6YK>zywQI<6%0Y9=neRW BLQzkalz0^=Q6@B&un#(z2b25 zlI+4IFsMpz>vXx8K&xt*@G(t^(Z2r~R$7V(`d+*A9_1@*ye9qQ1s4Se| z+K9)or!C)_s&1Q(CkJ#N)ha5P%S9?{QsO$^_-)-mx_IZ1!}=*jlgC;$->A=+^}~#s zb^5Na|D5{lv@`6tT7aJwyRNbCUi OM3Zhlv@G4vCi*sxjFbNE z3m_)I$D{aVFJ~y@6O;OcB>>`QWMC1X1oZ ZF|%JZQZNz GE>jAB0G9XMQFp~ z;?Z_!m^KtmY5&q#9; T~f)A0Wy`SM5LD#iL }x4${+y-jJiS6iIOuS+N||9lO1t~_ll$` zNd`7?2qa|4Os6JRsiZIsE;r@=F;C)J^+C-&?u#s>A?H*jH5H0Ulx=ut H$^vb$&o$O5VaXi7j C0jlA%3=Vk9gKf}<`b@#qkQ!ZHr Co_rDYPE=>6g-~t=idOh{kP2VG>13UP^ zl@M@NAxz;4<4C_2&aj4sH_@?jqDijYu!u*@01QWNm>sO+en`yX3`>|%xZG-sXH4S( zCRl4rjpgHT7|-=Gj>rDo;C5 WArr|L@lzE^?GBIF33^zc x%oO8R^pW>eJ3qwLtDCed0w%E`g`e4+pfwBzNUjbO=?4C z`Y(hQO@m9#>hvMH)vz}7sbfuRJHI-AoYtp`F~}cFsxQ?7Y-+6uH0${tE?6yz&=a3p zra(fq2D#>2w1<6(TTkQ9&yJE*!Ew=`igeo4j&O$|d%!@ZA}=w#mOx7=HI~VcR8X?( zKuL(Wch?ojLC%!m)(4)FQQB(Y4z~@gZSGkr5wOl`A~}^k>1bw`&w)m &W1_p#+G&w`3KIF>uH;}5Fb*w6j32ycZZ7)L|F`g_Pd$D~ulm-{ z7WJ-={byM(``TL-_U6oW=wBsw1yTaov;}D6ZI7t6dpM29c4q$Qe)iNd8`^;b{ (F)ATZa4+ zCFtA>Wa-O{{MN?_xHkyFuxGYmb#9<=;KY1@7jh0)5a*OxPw@_A=YZ6AH_W428pm+~ zNDjtFZWV=d7U)X=5l$;6cw@(0T{l_w;ALQ^E!bvvZ6rPY_Iw?fAyNlk!IE=(FmgPH zZS>cCd`B|EW`oe-8fvyjo2P%zK}y|YgS~fy2J(SZ=X(f9g4o4 v{-Iy!-Z!kjHA{?*+z|87(IQsjRW_J zwMaQ|cm?UUh#FK*nP)oM2Uq>(DfPsOJ@#n*h=kt(DfD($5JW5Js7>m~Qx21T=r@Av z<#raRfO9A<79nTiG+bO4fe}}YL02&t*MQ5jX9+n2xwsHK$TXg`bN=)QN?T`wb%;Mx z1x! {rn!#G2!cQ*CpdYUrAL}WGL^15n>2%%t4W) qA8ji$C MzSX9tA{zuXXQdvib2l CmL} `O@R_OnpmEN}Pwj@O zv%-&x)}NPZf9U0(@5N(^2de#-tneX-*@~zO>W&VH8xUz&63TUAQJ8lbTzSctAbO7{ z>7k1ym>`*)%4x0&sz5;6TSB@oMd_7m`mp|id0E_ImNlBAeaZ`EMwM- mQl>xuT07ojbawyCof4Jim%JI{RV9$Zf?+w=%+nqS%iKd7_aftlTE7;rDXUNv-1Q zv@~e9Qfs2AJFG?;yyZEZ#JRiHss6msORjMXXC_*?yasoI5RZ=fDemWP0hy2YR=Y?s zulQ=OskOKOT3w`ie}+4}6i2 w+vopD+JGY`*$AvZ7wJ~d A8F6k<+Dk+`rLub=U}(41`?bs%wkgV`UHGjndX^RVfDYG4Y$-H@k+mCq zhcmaNI2^wroRw1{wjfKk9K46TTXw=Bqjcu3(m=l&8mMs!PBjc7#OrsXX}!&Oc#PSo ze%pDFx_M4TzLCf{b0s>6{;P?owz#1fX`nikk&A}0wQu|h#dN}ur<=&2tHz4l$O96( zjvUEz!pM?b$?pNlmYm7Or^BjQu*AB$3_?C-yiaFKIyNk9x_Yj;%e>lFA)*|;m7u_X zX?W5~U{H&j+DfG3>bxSNL&+Abv0TfW=DAACEYcN1@VLF|N6PeRm!J}PeC(+JI-rW` znRFGn9LI?DnvY?GLfaf~?6bmN+#aLcaWf0Xc4WU|>{(;lAjVw42Z+N2%vQpJT7JZq zlHrjw8NqA2v>98s#4Nuc*TWAivgsMbU=wq!AeMyW!c `q ztZJXjz$AQiuW-WtK6iFU*BU6QGmF^}7mUtiS~AyI(R-Pa(h8NPr7FYR(E{y#TdAVE z{Itm%hQ1^*7-^?-z_VzIvtJ0))+&Y?U9ABtx(tkPZ%7h*H=O#*#3f9|GVG_wjG-uf z(f3=#?#$0@YsFmcI#8X{=Yxpz=Em>zx6B;4N;lVh`#FKEPnH_MaBa8>g^A92$25to zlN*{M^qJ$?(Uh!u<*do58^wt^c#F;0XHmMHCaaPyCzyQMn%xPBz1f}}4w)S$puE)2 z7=1)iC9fN+k*%zq{cZ~Etfj5EPOZD-3Cyf)jbVx-{$shttjogtebETqLlw-lecK!D z%2Bwgt!@6Wnv%T)^;Y=mLUGI+@v2tf%zxo~&E~tuf4gHi)KuDRP?%_$+C9DnxiWu} zysN6#3~F#p_Q499zop!OM9jb6a@Odkrw%F6ae0Oj&02gon4qZMue#hLe6Uw5XHf>2 z&zRIHw^}m l@eddLv=$Sw-)-SD z?b0 ^h)d6n_CpshvmI@Mzd3BFnTH+MiwMD?r(Xp6I;7-iqGn16Ssb9_cp6=#pOP zQ)uI;+EBr{;KcoVV@^!5OCy&3s+4Z#ugyTkUASub+reF(t_#b@J&qino4I_;uq~aq zj_S=O-180VW*qCM>EYP>=j*4;&JDOcXK(WcN@!KS0LeK4wJeY*$Kg${9(0M~-LGr) zuUxh2gAVD!fX-E9)(I#(6AG39{z_U7z;Ibu8As%IN|y(>-*-w~bKC8}ZkkR0(JQNx zoUVdkS> X6lsl@yGkNBp{-sP_>U~7eO*`9r+2j4|b$^!PTS&qDy+w3+wMm?&9{=eG zUEr9Ww^}*Ia#_`Mc+~^nrqu`0!{kL_eSv08rzH<@S}v#tJRn2g;V$odY`tS{tx&S* zh>ysua2{WBPPlZ=h;{7jnlsIP56%1lAr9f&iDLx>cr%2?&QR*-s|P)C(!zxuiVp2 zlJP8Wn7wW5x~@CM4f(e1?Wa%sonE)BPx`ue&gqKGoO0*O-1bY(=Rp?!Lu$mI-mFIR zDxuF^xS@2f)C}$FHT_IEk82O!Z!Leu@0TsT^SBK7lIh;+yiGJK-z2+&2>ZcUy}x+K z?&%@G+T@0EJH_d^fpYWC#d}F5n0K^9TUC-2O1iNvpj$>&?6WATR`DNuK5~6htcs z1?zT&Qr9+v19+e7zr`+Q*$IKgiIMm7A&-w`(6OvCpAn}MdTkiDN2^5KZF ?)bcZ&+q&H3o0msDI_ukFEK5Mb4)`|T5UZsl#fYlWfYZBXpwJnYjT;D zl%tw(q(p5~U^!$EWT~xmYNd6xs;gL1U|+T#ymq31#Kp$P$jSbCh0G``i;0H %I5Xb>GVV{{RCD1SF^#GiflS zQOh;Nl9qU1){U8WX;ro+@pQG@Xc3%{ZRxH-iZha=4Ui4#**kaAPM2ISY1xaovKoed z?LZFP$+M?VWd;e6c;+G@G;a)R*(^n5)31*VpDKAuszOy >)5kv?-|^gbcF!{C&P_d{Py!Sq;4dSzCH8j zpT8H^U`u^Pf2Sws_qpFaGMX)6(w~0>uGU=%!;Ll#QWD*#%z%hNIFN(|`T^h#GErFJ zhM2(zU4qjsxB-Ugq_mV-TJZwYT{;bxN?ZX#_0frQdF7Xkc1>j?T{8woSW9x<_?L>l z#HiL<9A@xJO-VLs;D>~O2;PVx&9v1d{A8()N)48?g*9;Hvl5s+jzOlDa9nexNg6>^ zC4fdcnT9!V%4uh39vUQHZS=X4B`Pe%avDzi{sDGTNZ(v|#*&4tr-l+xgd>tnFX42j zl8u(3;ia4cbl^~XQrD+DGXV M%;t;APjPI^kPf}HC%BH`%)M=ia0*_nn!Q7pj?uh*Qh1Qi!8Tt!* zx2{O>UZK<%W>zXj!IzI-b`|lDdD$2wZtCGG7I_0Z$t%jfA}ljdPzty3%s*|4^Ugfa zY^-BNh1hdXIuC91(RQ9I<$Orv7jx78P)B{|&xG78_0?Estu+NoTfOzyV26D))hT%W zV9~%lEm_OPwTL!zYKtxR1YOTIrIIX4_%@ZQxxM#Z{|tK8->nfoch+P_XE)P$cZp8m ztL0}nxI1k#d1{v*E_K~O-;L=*J#OrZ#6^NUcv*3?2sn^wsoWNhGD_Ym>6MD-w~#Jk z344uPh2rsAE4!At=1?bIg4q|4=qBqWx*O4!?xxDgmvO8K@bxj>>mZyat}6Jy&$Hxw zMmd51mhd|gufAtBd$%~Bn38%uz1c$Yy|(yL^eP?9h9OU3iF${nx;2h60jnh9fQR&Q z)3Eh9kO9V%P3IUVE%`A^QYHQxi|hncL5$VM4As( )beVnnKy B41VM`%RXEKgKGLjGjp2#M~vf%}8l6U;t z6_FRpQkwFV9cmwfNQuf;y7H9*8Rh##1 ft7 z$jqaH1Om!FT+D}P1pYxY)0UoAE|N%C@gy=^Gt3)$E_r#&A>`sGm;&CxaK76I9u%p~ zwwW $zIfrZtF+>jO6~YmsNzYN=;CD~s%ny}4yl3I+A2YrWYP rG&$Oz|%wu0#PJV1G zlPO9p$>PGuNnS-`f<)cx2wAeh(P+Bq!!GYCSx!t&v@Rz_DS8gu$#f>SJ*+L}d*@5v zt1Y*+_06w-hZf(2?)Sd{KG=Qb8{h&P*h&5E<$)K>V1p`5uHiv0#yX=^qVb`^71D-; z8+@4rBjt6yv8%)2#Hv$;{1(3L)&8b!WD}! zhSoy iBWA75SLy7YQhJ?GC-+>4`Z4XBxPmf6ha`Y|if zLDxyy)ri&wqmC5VtN{K?eo?e-W+@A4ty((Ml RZ@6oc5 zv8ZPoFjs+)7O|=dsgESGo!Yvlk`@z=HSMfhNwjddM)h_)EKbRq>QMazRuhrhp#7QJ zTDvZBW~+T|0`d>Aeg3wWa9rwaDmy!9R+mhly}Tzr4!7@~m#I`Zt~(EQ%|mr|`8NKW z>En{Mr-2spX0&~7>@b@?eSGeTwmf0*nyI>eV=8&`)-f-Wm%6p`=*p79&K7DpoM*}C zN88&yidVeQB~5X`S(EOS)7s@QKg_{be(IRpTmvnqdE9Q!^MTB~=RgnoPI4~vq8mLK zKR+8YcfNFe>aFHHd*;!3L-d<~Jj4&m% <$?)p cAsD=;+>#i}d(MXo@~?mEfq grhMsSB$xD{~yvT13D8vh4?r4f5mW@QVva7GqVuE#sy z_fRLpNwlL$-8B`}1voF*cbmjr4QF>8b8=wEbR4LBs>FO*lYu)JggoJaMgxRGc!U8l zc{@{rNZ5qEL4-~ig+Zr;QdosI2ZhDJdS0i4_NNEE(rb;Ag?gib{-u#JR;XM8xN6Nu zT^f~BS$9s-WFGF-c6kK|W9W5uNN$(WD`(gt=!Z~i_-AbQABIsVUU&>Fwsj0NZhiO~ zX_$Tl1}Q^^B}JBaf0tws7jb&gc{E}lc{fp;m}P?}gL i%Iy1fH+sK27Q5IYWKruU8p~`w^RKzeDLN~40u`cVtT@YLYHPo zdKH16G>qJsi*U7QofVFg6)1w`PaEiP*YarGMu)U`dA?WvY^-1_W~YC$n2^?Zi}yGt zTqsRvwU09Ajk_3G&A5OjM2FIbe5kj8>^Lpr@>$?ElIB#95($rvLVu1!eDjEi8_AJB zfrUl2XY3Y@FIO<|!dVBXjtW_Cgyu19!hX3|k-jAn68Kx-7n1bmO!}ykK0$>K=Uka2 zf|jU)g9LHqMT>|uQ>ti+u$Yz;d2wm5aW>c&iFZjif?c#TUTnFRB9}XGNtZa7jbe$F zJE@D1RfJ>+nB1t9{#TfW*@!%OFicp88M&CRhnSLCnT^$$mYJFIM43*vbYG{4$M$j$ zs9yhJgv()?nyCPo`A~6*Su_TRTZoL`0wF7PV_5#9g{jF0oT-$eX_D(yh;FEnb%>L< zxqZ3$539+4?Sf=?2U1POoaM!LE?8xpsBqFYgHa}muPBKa1$dnFm73Ra=#`Wkf|{wh zo5~50bXI_Gwm?FefV5(a{-%;Mb|$wcX2EDB WRnMaYXW|4{&quk+ N8E_VOf&R6aBpGU%$@!e-^+yaxf;y;|n24Qi5hi(w zWopS@AJZ~vDxzqrQD7lnAE!tz^O#8b2OD~Pfm*1>P^N@xsEX SqkNnI502bpE7uw>g8Sr>Qunq?GD{ZTNnKcv_?Cc57#(J>y=$ zhpNKFsgd|oy}6CqSYuh3hjKGo5sIt8p{kuKiOXqs-=&RuTBQ%CT_^#q;nkcI$)|0& zovhk CfoO(LN;gc%A!w6jhJ ~np<`hy2MUQlosCACv$3&0X98F}OBTF|5 z+pazNl(0stKeUZ=NTpUfjaT`jn)S2@NJ2JAqy^Hmp!l;~!>)mdEw6Q;`Ua(*HnUJm zFaC*?qZy<_I#daouYi`e152=6N|IQsnnAm@-t~}O`7q9Ut!pZ$( vwKBo_xDqokSpui@0<903|!QmfI m`->s r7n*MUvq z`>}>f!54hPBcQ !ab3UWk|(*43rwQ+IHI$1O=0)KF&o3fnZ)X9 z!#Iq=I!vR@cC!9ToQxnU#3V|!V$!zp^l31Rj_o*yPux{j%d_$JM)O+$SA4-4e7^+P zwLh79Ii-MKyFB~~z4JG(5G;>}a>9P4qWYI-@4FjCl(agks8&43Ic}%?Rx8V7r zBZZdS8Avrag4hZ(su-Q8_=)KixJR bQQYV %=vZ9H=N9nD74Ug&C4dok}L>WT+Mci z&EPyw+Puxw{EfVdb%Pkr>P!sMOvl}9&KuRMDr=|fT+heQ&RA^60<2H=+|Nlk&XQct zyQnCa82*YO_`|z%r+4Yk4DA5;T)_fePkhL~_2+DkY@ZU`(3|_v+)T+U 94L+=Hd;pnxWg%_tqwQ=-TytS#C%j4T|}4L#HEJkSm7!v7Y=6}WEX zIk-HnxjwDW)#}QD 3OX|8 -3?#jGlGb+p&seOQ`MfZ?!q p=)0F<5AOkFR&xGXA&JE>@@c3N`P z{%SyUYIv4Yu+S>X%<7%s+EL!cD5CtAf_H*mrqJ5Ts=Uq0s(iNsl-rH;oqns90UFw% z0?;%)9~OAp7J9@OU7J2dmH4W!5-ZX?)TB10pA7jdU^u)ht+w9gX3My?I*s1zSCaR_ zkO9n+^1P4GO~2Bu*R>J9++xOLe4}9tz+zmYp?2Q>vkSr~l4vW`P>aURcA?tspae|3 z6+N*H3a0kGsF7?4T0PzUeU>geL@?{f5>AZpZGtEYYKWYk{d#>wEqro0UTg}Mo9xG; zHN|XNgV8D$9yH=Zyr(kBx`4^n-mKnAOGNHS(oss_`?BN=dXkt1e>)_|QU2imDxBl_ zrsW|mn-W@wLexV*sfW2~ 7VA=8B&iF5b2(j!mAx-0h_;>E>EW zTkdVscfPXoHb-oWjRF_vLTKhw1(833$^ozmPxg=NaiLt^yKQ8tZE_YDcx@Sjv^$D; zddZDMzKk1qvCK|V-CPV;>3g@nqF&?R 7)#bq&{1n)TcI$La z%)0)oyx!}0JwE3&(vA$!zOd7N?F3Qm?o7#^io2De?0<_& z*&B=4PB+?K*k|49EQ`EWXIf?E*G>oTE{^5p4jktW(Z~MHEeh<+`-bOQhVW HjPoh?{Vqb#?x7)O+dBH+o2sXn`;Nb#G#>PFJOx?M48Y~12nu4hYTHaqan zQSd2!@Kc=NhFpwDKF>kDo_s#u10IoXA}Msv;MU#dC)}|7R<_R9RQkf~yk70dF5mY_ zuQY3a<;cY(48bcOk?wte3eL4+-lK3#?+6+KmTc7WUb`p{;zxh9S?{0{`F%}Kv?%+b z2oJ{d*;GS4p7JN-9tU1E{$vY*fL~9`VW00gcE*0*qXwMzHrmBFs-RNe;t|@&R^^^x zUh*7kv^}2ZCeJl}&+U8c;70x4AWZoBnk!?z?gq}AR9<@at$JUskNf`ou482AT$Qnv zf6|vP)}U^eqaL$RU6#(hI;cKzfE3()>*|?avl&m{ix*uTf9ZPpmYm$D5>v^d*qX6V z@Y`(gZOzz6v+L7eL$j~){*E++v-jI?97eD2@h<)vNc2QL{$tbq*U$d&FHG)#
}*y*TU5yZ>M)j$~;{Louvu%LYJ7%!07Ygb*@( z)QpUi<|pJ3i^wD-sB9)1N5$kAby~03tai)oR#Jhmcs!03aJ3svL{(O;Z*AO5U)Jvu zsC~M}`~QG}f`bqP95OUEXKOosOb!bQkxP$#7LkvWl8{iHkp7ZYm6Mv6qC9h)pp>Z( zJ(QlCv7DNiuopp5p_QPdr#_^-xu|ZRtrTs9$;!*j&4&R4(9+S=(}+2WXl%tkzsB5B z-5Ips+_mB4A3=Hq7V6(WU?@krjQMV+qhmPt?Bg=9RnM0X zg9;r=Gz7(o6R)MQsH2h1TmoIC ~O{ 6&dn hr`FsR^z5Jo8BL(Umk5gMjVH(^l@X13vnAciO+ zASrBSVgm>=HDXZJ`PJ5nFvck3j2)!l!i^D`fnkC)_UPk}Kn6LWjX1ghLyFo6spOJO zHtFOaM798pkvb;ABS`JMXwZ{fcIoAp%0$WjLJU+Q+1GnDab=uuV7BSzn{WytW;6gy z`9hT!sVH1mieb@VoPY)@XrOaGP-b*`wj>35?5t*;e*n?folmON_vfIPW~ym&V#45n zophRcnxb0G6w;ofh{dLDz-{X4tFQ(rW&~2=xm1#*TBd7PfT@}qGQGws?6AZ-6s4yR z*m)$PxW?40qVyy*mbAa>q-L?$W~(h8QBH8Ds7>YSYj8Bh(a~SJ2D|OL?6#W(k;p AY(o8ok+KDEbVPeTnS8esxTZDY$$hV&9mkBfb5w@S^HM&LE9gbZGcWTqY z9}-$(-Hg_U)?4ys4d%Tni%qnRZkm0U;2;(Fx#%7-tO?b&-f~l@0-X}f3-gu8f&HZ4 zt@Vlcmg5?sZ{UgZ%~Rt+b&Eod;Hqk0#SRm`iz$_6{Ff)?t(J*;tdECQKj*z3_qDXe zz8$67c^5kD{j`P4wZNMFXz;eVPPj>`K->B%$@@-wzYWLo@Zka%&zA6jlg`Ys5hy!3 z!vXc?l2(6z{?pqIqvOc@`2M~>|L2)^zBg_A0}du+qnOUP4_Yj7%s|R=7&gU59)^L5 z#(=^=f3Zq7_pl%J#sVHx3|*r!t| zGmNt&moHV58o)Udf30dJ|0451Um4RR+=Jl;lUTv*WO8HZ^hPa}fG{#$ahKD9*nV7r z9oOXtW3gLaDYoaGR3$`v_Q7ZMhTxytl(JH{D^LA~r#XgpPh$BgpFAZ9(A_CCpycr$ zPS*0q_WaQn5qoI$n%GZRgcNtcD~?J*xK2ae@L4AJr5Gw`vM*bZB$}O9!(co04Fs za5zg#!}QW3>C$dqd&o{3Sp=Z&bEqtJs!p*a)uE1nZtp}YFB|eR!BrFpzq4xJ!aAR1 z5~8bOJzoL-T;?*FCN-^ajjP9SrU5L<^{#kzSA~dnp+(LBYJd%_U P z_qy2St#Xr#T-R +kO$9v&VW8=I7vbm`Ki)XS;q zY3aGSxuqqgmF1Py*Qy(CG&D6f-MV?}PTQS(ckcCc_w?QGd+^`^^9gfobZla5VrFLM z`Sa(itE=nl>)*b8J2*J_`}gnvlKB4x<`?w;QC0sJ|5p>h#$uL*k=>d|t@SaJ5k@zh z0y_=jJsK$f3DaMapR9FIBD8dEmH9(Q&L-M?=}U3A`|8_q|D|W@8>U($mrz8FY*c zErwqiD~>5Dk`^s47MI3UR!T~i->9v-QQ1)6e6yvbwz0MC&fSiCGIh6$d+yz@>bv!* zspG+e;+h6Y*?d`yLg2Ktf}FhEGwJDR%(KP0<;B&NH*ep)THDy%+TOyvk`k9)oZ9%h zA|oy?H}zHS;PamR(ZtH@H$as*#Q{B-_LkVe=bVw> *%ix&KVR%yC$cgTLg=`TjFgZ0a80n+%17cPNzSLMRn^RivqUtfs|q?g(j zpS3Phe5c%fygodVsr)y;CBSc_n_K4a{6zU3|5wxJH7?BDe$X}b=(>3(evV2=g|Q2f z(c$Yv*d63;BDuDA5b}ykM3IKX3^GudoXWylG!X=OAnZn-s{?y-aAR>)JPib9<0al* ze0uuChp%fE%D07gp`9qC_yzp>XU%K;3i4LddZzusb4QWygGEh8KyV~_4+Mt0?YTk) zb*Kage;kqkVULJ@1ACx^I}PC$2q8KmSOk4AjZ4c31QCVy(IAtUT0DEV3G>Az97}NX z(lG-M=Ge*F8&utq%XoT0pt5j= E~@j(zoqMH$V^PuPBN2{t; z;ahE2#tg!3E9BddX3uJAGjLSaS}KeW2#KJKwJ|>5 bK7D%vu&eGd zp~4Y+gK&l0xFINo_I{Y(xP;)xiHK%`{%oi)K~N|V9s0vEgf;-mOX&chs&>&}rR8wi z_`fI|ZR!V4Ein5F6|Mc$_~*=CIMNeoFN>wD5Fo b?=nVjXuzQ_LaD>y3nPVQDB;a`^f;NhS;DJ;x@#w@=cEBlq83sl6 zfjqd@egYu$9)9gmY7ak^#YHs$!TS0EC`^KepOSc0qYJ>jQ)ufT#GWC*PC)=M0apK& z|F-7l)0oHX#~1tF2=O8bukN0jO&$f}z8-v^5C#tSvAQlp&&6?MCcOD1dIKujIKX6w zB^8RX@xpOn2n3H#9sW@a|J9#iPSb)QMF0@!;0!zAEy!;99*D31aT#!mfFC0(q%P{H zf?5snU?G|qr-3@~^%Nc=f&{n}(W!it8*gJE0E`L`Ync>>h&iP~44goR7ic-i3H-P( z`7E0O^WQ}}4XQ}h|M8GJm6L>CRILpRndXi;n?#6e3If|*!-omcm@<0IDBfu1(?TnY zG9_L=ztHQl>)oo;3&<$z+35OA%-)gl~rlGIauRCgH)LWBe3LevhWX_+lg2Ck)Zc z&?zvXf_|BMy*(W3JFkn5Brlu L*;jytm}g40@v-oHfogGo0|`cGILA`cr*O$p8Eu}yR&?Gvf9BEkT>0qPQW zmfWfglJ-WRpiEW=e@+B_SJ_M3cj^{%Um3^uL5T_y>bM4zKm$ Qj8{pxATUj3EC!Jx^7hINJ;l~FwrUi$7%^e_*;vxmi}9JzZPx! i2+JSriqqE|RFo>41T<7c#0#^VzVEpQNzAlTx9~FVt*Y1HL z7Vnn7y6Sr}-0P(>)4$dHTHu$a^5k>-w=22Zqcg9)ob|g0_Ie!-% 3 E74E__=+~U; zkB_+TWm)~btKtIO^-`?@RHOSiW@d=nlIx~T>~ru!&A?@XA51hCZ~@~g*(;cjEi0aZ z>}vfM9yny6owV7g%$W6Utgf})w(^ygcK%vsHp3EJ4~hXgzfdCQ<%2GM<(ety?|M5# z_E_n>>km@Y1`YN9*RM41XV-X+ZT$6A`Sa^ptnSzBc@pTEhc5LZTX((iY{-q5?$aT} zvsYVl#4?3m)aF7dpICw)Se6%lFSw2EpFa55Picb#TzRot(wyV}7Jk*EO05gPKA0|> zI>(fge3y~Ysdj0 >2WDFr9 e(`k}fP5Knt~_NIB|ve<`b z5I{Gv|Hks@+}QmXwx`kBuTD*gCEw*LIcu2wr+4#E4^;9izpzkzK |Y8wT|<0G6p%~4suMhnZ`1~ Ww&g-hjmxu0%X%2>KgU8m;F^CguFDGR*8!Y93#lo zeNhKoIY=xQFy)Glf=~%N 1|N)V@QH_dzI zwr}+a5f-LTx+Cr$M1F{i^1%YXMlyXDfhD;VZd~~7lF$$f$>k!K4sA)UTE 2o7PK`IkOGg4y-%*j8Z=tyy)CCZPgq@O zWDr?91d}G}(SBsBfd-o#5HOtC2y>cD*A4N{MFJPDCq-lQBBr%bK4bX&1v}z|1BfW5 z7X*;E2*tAcC|cBqxKrP*ni1i6Od{YrYQ&9 4oHkW5SrI_nNxUNk5f&MXgb zh%U)H+PIM1rLEj3espBctCjURow!7Dy`C0Hhe%41C6`E+vit$svW8sIy2_;vVX4lJ z0cl4^CqyTm`AhYdGMy24aRF?2o28_UuGZTG4KpZ^4>#g$0rV6J<=Vt0jPK{t>=lr$ zkHwj%$GD7MUu=oTq7J^!J@%+G(lJvHoR+{UzNBvD(6sIOdDGKPsmzzZjHL`I_j*v~ z&ynC5s+G3o3)e0s{kmAA8;V71xV;RGGuJ9DbEm`y1+xdiWXmxn`p&J6fh9Q6&8xcp zUMF=a1r|V+l?EF+A(NqbP#+W@O8JK#`{()T;w6o8QGI*eiV)fJr%zIp{41)q%ZrW@ zdf2lbHU;BcO&jH|mRozJ#aV~MYA@dlcB%Awv|HwKU%UUM=V6IvQ$zVJ_p6{^VV}E# z8M~UpN+~8y+SAth-PSeyWPL8B(~lLB{~11|=%$f AhzRtji_rb8k0TCGR{B(ybtt8>FT^GavNU;a;>(6hJ_q !rEec
%|p{R4>kf@g#fH7Ih z`7>hoZq(*aTvnCH35kF@C0RQj96?*eskx^hF^SwuNca_?@x}@ejwb(oq4mp+us-be zchmM%o3>;xwIN%hUMTead$@2T!$B5wpWq?n6p6Cb3&_H>G{+noI&r-}5o$^NXzBGh zuCDQe9yShup?!ZmPi@iD3QIFMvLrMTf;{A!485Z6HneE7(mb-vH7ffY$&L66Brzc* z0K-{aPb4dArO9_SCJU7~OjShmq|pp67c9FKcUzC5(2WnNwiI8DhUNpAe6FK7{}%KG z*XT=O8rp{Kk^x#F@#Ne7AjwHPBosa1Y~y!)GxX=hnayZax4!oK3!HxD2r8)KzQgMZ z!f0w#U75=rD>OfoWKR}T>JyjJ26jUtKQ{^n$yDz@&;5LeZsc>++|dm9Y4oW(q93c@ zvQAJH^19#DUgLF7fJ75yYY*wUbE(S^xuK@n?GU%wE)=6Z*Hm!ZT4OPeOn7fvx^r`< zPb0uW5)%%rFA~)CF8@fl{@ Ng;hB>)WPTR{BpuV_&ioZL`qe`p6QOQ+HRJ*U^gC^?Zsp rpz>%9Km2WBUA s&&;@#l@+i3&A7$zDqlv-s`(t8Hzrs^%)-060o7QCj|LpbQvNglR&Owl@MFq04% zGOCV!3Xh$X)7T%j{ BFBWH9%P)t5e&_|>Um$c^_@1a9y{ ob{ie}`{tyJaPE_K_KW^iR zf5)Hb4RPA&=$G_C4=PR4VsyKLCC#(oX~8s!Ng(YB=V#-6dWo>;K)0=agMKjI%|zLT zr1K{q?Z+8O4qp{+=xh3QI*lZ*$&xTwd>ACm&} iRNAjz7reyVc5h)C$J&tVn%F+?gI|U ZI4vhOM)+5C+2JTOwU%ARsH_t`N|IP|5z x83YX7R8+!E?;NEXQe!zxODP*jbE(^sTNZ1E`igr!?o*%&z5S6_-87YoJbwB zV_SQZ;~%=ja=U)9^w<7rGsf(KP;&^(JJZ5mLKc60JnNBWu`bEz@lTI45?&}AlS{~; zT`+2K-tPK>-TlBDVFzhH8#j3wHTUK8GZ&NS+9h*>23UPu#E$Nd46XHpuX|@f(`oW= z9-TSf=;oJjM16{s5T%k&UZiC?Tse?C7i?{&dwIJ5!2uB+1Hpg)bb374`mdgI0O{P` zf#D~&)2yY@(yfw3 ZmWg$h)*kT6Zjwh0-qRp>|R{*SotoF-amf4VQ@NGe_h)w z=;`1ZH-S0fz~+R1E2B;mIaCTATzhF-bJGehm#!OCsO=vm>lam${q&EL eeJFH7Z$XW8GAZ!?}Mg(fCg5*~hF z()C#>O$DFucqEWzvB_8Ire10PfnTi5q1FA9psk#n{Oig4ZdENdoM3-Vs fwFEp!O{2C -x1~qC4 zbYNo*vtH{9)~`>fBzqi7n)+ON+xqnueF#-TTKDk0?{Vi8=wChr6-Rq;>E9jQxMQS@ zhTrJJyp{VMHtkplB0v=BJa1JfYi(0Waz3L4<3#Hqm7LJ#bTA5Wn3zr_uw>bzdg(N5 z5Z`q~A{+PAoTy!$-Z}YfjssAA4GEd`&@gVt4M;54gOSsD7mEF_tlV0JiB>}4C=sW* zo7_+ilmIrVb`5}nQD8;nXsz5h8y`}@P`egHhjSxTaUJD&$N+c_(J_5Li#`f1*EFCO zq|(~f`ilJK@&=(Cym{yhClQYu?Cf^41;(QGs_d;fPEyd7rY;Vb?DVRcRsG;e$QWS` zzD7%f+#&t&MV@VMX5&OaiD+P0X<2fzoIQF!f?=!7Ye(y$_Mq8$ ZD z8D2c_LJH34bbK8nuLBprB4{^q4AywBHfJLMu*?oSnB{hiq^6c5lK_&e0|qEs5lRBU zBlK7_0j_??C3_n1r{0154sXzR4!O`I$fk~v>xTA*-=RlAYa?!P;3KG}($al6LFc60 zJb{BL^Jf)5w4AAUC_ITa27jMR8-qa&YU!9&b5)SYJM>d=nDW}b7=)(%0rVb9s6}#- z=nix}?g~8Z@#>Z gr#GS@q zl)7@qi+ast3?I`YM4Lv!@Ej|$fPLd1OP*l8dp)|*h9~%e#LAK>T7iKUS{^zAiXKl# z-a9Bwwo;?fz^}P&sPo8m^6TBFrBiD$i8?ag5M{Yq@7zQqpeS}z?%Z3>@zHGmqD*T0 zQuL;7?UDzt5g_bjISbp|Xl^PmzR)?FUZkBB4jpR9TRV7mE#Fj3>Vl#nTM259OmF@d zYXSC=V{;PZ^laI?wc|sIP3Ojlv; zl-WaTi&1PU$x~4m!YP@;DzF;r)RtG70N>Mk7UKo zY-pgAz+Z6CfHpg8Z}+Xt4n=aOf7j^C>uZ!hQfkvHJ6G%he?uDLyB`M-B1U@SDxFCi zg{z-R%-(~)-!FR6Uw*4rt&SXOQvG3n|0VrdySCMVk95z fxF;{5Ys3#JdHDOBb-X zV)ptxTg8i7ZkVFH8>HoQ6fqXC8NF+8UdAFLdP(_g%bWmDNglLqzoo*U+2uSEob_Bl zStI@ X4p%(a4w rO0{$F_x2(CVbE%1hZ? z{#v|Ob#ppUS}z1a%F!|^)3fdC;$0NwoojpTtaR?t-0GUtc*zLYBlR+4TY6C6d}i9Q za)nFlmP3kr3$d);<=R}el$p#-`?)Q2ago?VukW_N`YpkaLk!&J55D*%JH?N`>)oNh z?_GGVQlSc&i@jdhqV3FC^sX*QZFU3J+)CoOe0xy>K}~gNUyr%n$AA&H^FlC87Fei| zcEv$Nbd2m@)1W1^CR3 CZGw4l{<>(*)!CFN(lg(q15l2Q{|DB+Z{5jB;^DU1a8UGDfz)9WwU!; z89C?c-LD}HC6DKPBlysCLsbCluc@B2nC%IfVy^-w&H+M&!PZYuuu%z_7MVQ6*WR4o z5{jG2%Q!SjC$`gF;H<{|NvALtmbOl+)%>ti*dgB``mRr|d;qkW=)o_5WQ=9@+2o0( zyXO~>f}3;&N9H7`y)cA=0BS-)+|K#-mV1n79^WVBnmOmy^pDxB%+C?JvE`^pu!Sr` zCJ3JtgH^b+js9NtO)aBPux`sw*b?WBe}0P#Cj(a5@6phVFUtMBL4PvP%1Evhg;f|Q z^*6e$nau6GD^$-`+EDid3c&4hrMX>vLYmfD_jFKMz0y@hQ}oCx;|x Qv57YQA8@n@a$Y)y4}w3! ROX5{2%0X|}Ba(S 3t?a2l81E_Lk;z;hppoHd1Rgxca(>t9pqTn^k}P9XhTqq8@aiMJ zrx%6Rkcq`sEiVIjbdW~e>Xa@@hn>^>1D-LGsuw+i^%O|#7U@fXY0p#g^l&P)j*Fw6 zx&mtSMZjX9Ikx9_^5m&wn+YU+7RM_N1ig8|=PfU;3Jz+)<+pJ )kj8h9Kd-IozjNNwdIvK+MbMBafp2V$Y8L(Bqb8&`1?#9j z{4_GX>vLt_ftmPv31)r9|LGZzob#k48O=vRw5rgIvB_HrO3DJZSQBULwY!DrlYLGk zsN#>g&JViBYqw4n`uup^X+heeJsVT0pD{CyMLA(>+_Gew_>;~$EzQy3?T2QinjYOj z_e(}vWJ>R@^-`PGD?dIg>=EGqES_-zG{CWepp3qrS_d1PoN+*&J?~c6Jb2-@7VD=i z6Q!qFl|JIVX6rQA6a(YU88un0eSr;R8O^MHD_GMEsk4ETt)kVPC1`d&n780DyRk84 zwlwk5n^plNg47=3{nWjOFsziy;r?At }XejN+zfZJlWz(|yHHZxO?&dgjo`=;>bvH4kbi%DF|1fGS#8 zXkshR6__Ni++ss0_U ftz6(0R4_}jUGOV*D+PBTAq4Q@;`&)#L~ zI1a3JAU}2Rl!39YKOyd+kNeyHH9-7};Nv*9uB@s>-J0M#1Ll{$Cj~Beql!=nf_x!! zE!VHvs;X;O^BS?;m6XpitYG0Ms=-z*y9n=k 8@^iLl^NW{4VD(Y)$jT=!K`wC6si*+Oj<(@6pjiauXA?h!+|k0<2L zLipPAX{u5D>nBfCiO(lxIo;d zLLt`Yx9?>mqMZz0qJ9)!e@B}2R3cf<^Kk=(IcqXfM``ipzl_;=TKgNkCl%@}F#9R7 z7!BqDATp4qLkr67%r#`A1QmYAF8D!;6S%n{X(m7{h}}XNaLTAP|4kPk3_0-;EQv^q zZuaL+{{#lurdhrI;(37{K7)wOR6`d9jOn<9OUzdpzA}kfrN<352+~<8S$ddn><&$k z+nm2x;rn6MlH1%WipFEw;C);m087gXJka1 z#JqyhN|%j|-{t4$431nmNc 1_J85dRT1O=kb!jq#3lxT*yEF`)S#VK1Wzl9e- z4o3(;f{3Hq%tj#zKuFwA^bqVxceM;w-xu@KoLh7=U-0@$;8wV&M6!mrvDUQrpJr># z@ZAY=)zBRA=`l8j;kVwq-Bska5>$NOxSzF44ym{JvWxbyQ>M_z3YIAG>uSeHuhncC zYV8M3^M`tienG%sbti5Hb96W%m 7~s8Q|PNJhP5 z(H3*z(Don7hEYL8O1CdJeh|#rki@n_L~=ZOK_$tqd5LUdH9K8$NM~b4Q`9ZU5puxT z9>xKxceU{JtFj?^<}$^dBsDJmBt4z85Twlf(5_QiDt9PS3n>So*?4NLYw(NlX1I zU NsPn>s9@z;_T>VJLkr!Yyt9S99_uIa zvOIG#%$pqvbU#a+LV0hk?0lWG))p25$U3Lyx5>o6pfUh}J=h$1xW&)2xPTKPHrguh zI)<&Mn(GKsQOi21MLPOmd7E`gYZ>wvQh_w&om(sSahl)t8S JAB{PeVlKaQqr@~{iGuBqH%OHBC| zF0to x`-1{JBZr^Hj8oYc=lE|iUU%Ewkjn6v>a6TT^MstW62oWWR^5Is7 zWBYQLMD7|QPIFAlbe%sUUF|a}8kboYvMuW&qu6OxrQE0$O0<7Ym0`51qlOT1bz!nu zV^gWPCkOXZwhNA_ -DkSl}{H`cik|kZKsz5(vEeqWs<9mGB1!J2c&kWy3z1 ze%?iT(=tEK>I$jPXp~VCFM4_kl$~w6W5J01x81^)Tx(y{rG~# jrU*dZ5aEAz6u#7 YzDoiTJ__``Th!_#=g@A+(&E^!j-#=sjw25X52r+NJ2#hHE+*IBJ^1jxq zKd0Po-_}hqCvi2IqGYYp+KR_gO_s~BKHbD)CI~lYvN9(;KU_~OOg?vLTfd#G_Cwbb z6aQD(C~Sz|V-6&;Z_YXZH2q-sushG-AU+|8MTmJ*pf5Le_+q^pet#_*FxO!&HUnW; zJ&=EMmu Nq5^f=t_@u5H3V6ArXlg-qz|H>J&e`?yq>v6$ec!=!n%(y zj}esD4pf3Qm#uE&W=#up^xO*_ZIBKeV+O$2im>}cjlK~>Q|v^ex#cZJ%N)I&F&{E^ zSbiRH_f{o$ZuViz+I8{4pH=AE3s;4>uJG`&p-BE^QKv$oPt{VvJlEHm<%02hw;qeB zJ~?EJZP*?>) *gi@owngo)6sky507C;Q#2 z9W^VwVMA8Q0b@=dINbk&n=!_tIZmqA&YmrrX9RQ)V9Hm>ih0=cK1~metO$ODX9_Ga z-W3er>$TqOHEhgoR`5RR{Ln!`dJKa)iW@svd=#YjQwV5txwK2!MGpdv%fZ54@q*Pt zZSPWWr}TNN3ug8j{az*x5CKF*+r_@32TQXXRjb9l7k!zi!QM0q$49bouD} IbF2nrE&g;|Vf)dr`*H&t$&OkL zaEy9zt6S(>@f!YWlG8qz#H*7txNq|Y9J@$;Psl#| Mzw5G#9Q_CTwjqhA^h z3}Nnt7=yv&22`{nT97W+V *$&*SX)z5R@z;riq