clean up some files
This commit is contained in:
parent
e0a5ee79e1
commit
3db426adb4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lib/asm-9.2.jar
BIN
lib/asm-9.2.jar
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
339
proguard/LICENSE
339
proguard/LICENSE
@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
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 Lesser 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.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
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:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
@ -1,14 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Start-up script for ProGuard -- free class file shrinker, optimizer,
|
||||
REM obfuscator, and preverifier for Java bytecode.
|
||||
REM
|
||||
REM Note: when passing file names containing spaces to this script,
|
||||
REM you'll have to add escaped quotes around them, e.g.
|
||||
REM "\"C:/My Directory/My File.txt\""
|
||||
|
||||
IF EXIST "%PROGUARD_HOME%" GOTO home
|
||||
SET PROGUARD_HOME=%~dp0\..
|
||||
:home
|
||||
|
||||
java -jar "%PROGUARD_HOME%\lib\proguard.jar" %*
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Start-up script for ProGuard -- free class file shrinker, optimizer,
|
||||
# obfuscator, and preverifier for Java bytecode.
|
||||
#
|
||||
# Note: when passing file names containing spaces to this script,
|
||||
# you'll have to add escaped quotes around them, e.g.
|
||||
# "\"/My Directory/My File.txt\""
|
||||
|
||||
# Account for possibly missing/basic readlink.
|
||||
# POSIX conformant (dash/ksh/zsh/bash).
|
||||
PROGUARD=`readlink -f "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD=`readlink "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD="$0"
|
||||
fi
|
||||
fi
|
||||
|
||||
PROGUARD_HOME=`dirname "$PROGUARD"`/..
|
||||
|
||||
java -jar "$PROGUARD_HOME/lib/proguard.jar" "$@"
|
@ -1,14 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Start-up script for the GUI of ProGuard -- free class file shrinker,
|
||||
REM optimizer, obfuscator, and preverifier for Java bytecode.
|
||||
REM
|
||||
REM Note: when passing file names containing spaces to this script,
|
||||
REM you'll have to add escaped quotes around them, e.g.
|
||||
REM "\"C:/My Directory/My File.txt\""
|
||||
|
||||
IF EXIST "%PROGUARD_HOME%" GOTO home
|
||||
SET PROGUARD_HOME=%~dp0\..
|
||||
:home
|
||||
|
||||
java -jar "%PROGUARD_HOME%\lib\proguardgui.jar" %*
|
@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Start-up script for the GUI of ProGuard -- free class file shrinker,
|
||||
# optimizer, obfuscator, and preverifier for Java bytecode.
|
||||
#
|
||||
# Note: when passing file names containing spaces to this script,
|
||||
# you'll have to add escaped quotes around them, e.g.
|
||||
# "\"/My Directory/My File.txt\""
|
||||
|
||||
# Account for possibly missing/basic readlink.
|
||||
# POSIX conformant (dash/ksh/zsh/bash).
|
||||
PROGUARD=`readlink -f "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD=`readlink "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD="$0"
|
||||
fi
|
||||
fi
|
||||
|
||||
PROGUARD_HOME=`dirname "$PROGUARD"`/..
|
||||
|
||||
# On Linux, Java 1.6.0_24 and higher hang when starting the GUI:
|
||||
# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7027598
|
||||
# We're using the -D option as a workaround.
|
||||
java -DsuppressSwingDropSupport=true -jar "$PROGUARD_HOME/lib/proguardgui.jar" "$@"
|
@ -1,14 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Start-up script for Retrace -- companion tool for ProGuard, free class file
|
||||
REM shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
|
||||
REM
|
||||
REM Note: when passing file names containing spaces to this script,
|
||||
REM you'll have to add escaped quotes around them, e.g.
|
||||
REM "\"C:/My Directory/My File.txt\""
|
||||
|
||||
IF EXIST "%PROGUARD_HOME%" GOTO home
|
||||
SET PROGUARD_HOME=%~dp0\..
|
||||
:home
|
||||
|
||||
java -jar "%PROGUARD_HOME%\lib\retrace.jar" %*
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Start-up script for Retrace -- companion tool for ProGuard, free class file
|
||||
# shrinker, optimizer, obfuscator, and preverifier for Java bytecode.
|
||||
#
|
||||
# Note: when passing file names containing spaces to this script,
|
||||
# you'll have to add escaped quotes around them, e.g.
|
||||
# "\"/My Directory/My File.txt\""
|
||||
|
||||
# Account for possibly missing/basic readlink.
|
||||
# POSIX conformant (dash/ksh/zsh/bash).
|
||||
PROGUARD=`readlink -f "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD=`readlink "$0" 2>/dev/null`
|
||||
if test "$PROGUARD" = ''
|
||||
then
|
||||
PROGUARD="$0"
|
||||
fi
|
||||
fi
|
||||
|
||||
PROGUARD_HOME=`dirname "$PROGUARD"`/..
|
||||
|
||||
java -jar "$PROGUARD_HOME/lib/retrace.jar" "$@"
|
@ -1,19 +0,0 @@
|
||||
**ProGuard** is distributed under the terms of the GNU General Public License.
|
||||
Please consult the [license page](license.md) for more details.
|
||||
|
||||
ProGuard is written in Java, so it requires a Java Runtime Environment
|
||||
(JRE 1.8 or higher).
|
||||
|
||||
You can download ProGuard in various forms:
|
||||
|
||||
- [Pre-built artifacts](https://search.maven.org/search?q=g:com.guardsquare) at Maven Central
|
||||
- A [Git repository of the source code](https://github.com/Guardsquare/proguard) at Github
|
||||
- The [complete ProGuard manual](https://www.guardsquare.com/proguard) at Guardsquare
|
||||
|
||||
You can find major releases, minor releases with important bug fixes, and
|
||||
beta releases with the latest new features and any less urgent bug fixes.
|
||||
|
||||
If you're still working with an older version of ProGuard, check out the
|
||||
[release notes](releasenotes.md), to see if you're missing something essential.
|
||||
Unless noted otherwise, ProGuard remains compatible across versions, so
|
||||
don't be afraid to update.
|
@ -1,36 +0,0 @@
|
||||
**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. The
|
||||
resulting applications and libraries are smaller, faster, and a bit better
|
||||
hardened against reverse engineering.
|
||||
|
||||
Typical applications:
|
||||
|
||||
- Reducing the size of apps for faster downloads, shorter startup
|
||||
times, and smaller memory footprints.
|
||||
- Optimizing code for better performance on mobile devices.
|
||||
|
||||
**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. It is already part of Google's Android SDK, where it can be enabled
|
||||
with a simple flag.
|
||||
|
||||
**ProGuard** provides basic protection against reverse engineering and
|
||||
tampering, with basic name obfuscation.
|
||||
[**DexGuard**](http://www.guardsquare.com/dexguard), its specialized
|
||||
commercial extension for Android, focuses further on the protection of apps,
|
||||
additionally optimizing, obfuscating and encrypting strings, classes,
|
||||
resources, resource files, asset files, and native libraries. Professional
|
||||
developers should definitely consider it for security-sensitive apps.
|
||||
|
@ -1,212 +0,0 @@
|
||||
## What is shrinking? {: #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 name obfuscation? {: #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. Shrinkers such as **ProGuard** can remove the debugging
|
||||
information and replace all names by meaningless character sequences, making
|
||||
apps smaller. The program remains functionally equivalent, except for the class
|
||||
names, method names, and line numbers given in exception stack traces.
|
||||
|
||||
## What is preverification? {: #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** automatically preverifies the code that it processes.
|
||||
|
||||
## What kind of optimizations does ProGuard support? {: #optimization}
|
||||
|
||||
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:
|
||||
|
||||
- Evaluate constant expressions.
|
||||
- Remove unnecessary field accesses and method calls.
|
||||
- Remove unnecessary branches.
|
||||
- Remove unnecessary comparisons and instanceof tests.
|
||||
- Remove unused code blocks.
|
||||
- Merge identical code blocks.
|
||||
- Reduce variable allocation.
|
||||
- Remove write-only fields and unused method parameters.
|
||||
- Inline constant fields, method parameters, and return values.
|
||||
- Inline methods that are short or only called once.
|
||||
- Simplify tail recursion calls.
|
||||
- Merge classes and interfaces.
|
||||
- Make methods private, static, and final when possible.
|
||||
- Make classes static and final when possible.
|
||||
- Replace interfaces that have single implementations.
|
||||
- Perform over 200 peephole optimizations, like replacing `"The answer is
|
||||
"+42` by `"The answer is 42"`.
|
||||
- Optionally remove logging code.
|
||||
|
||||
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? {: #commercial}
|
||||
|
||||
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, 5,..., 19? {: #jdk1.4}
|
||||
|
||||
Yes, **ProGuard** supports all JDKs from 1.1 up to and including 19. 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. Java 8 added more attributes and
|
||||
default methods. Java 9 added support for modules. Java 11 added dynamic
|
||||
constants and nest-based access control. Java 14 added records. Java 15
|
||||
added sealed classes.
|
||||
**ProGuard** handles all versions correctly.
|
||||
|
||||
## Does ProGuard work with Java Micro Edition? {: #jme}
|
||||
|
||||
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 Support Android Apps?
|
||||
|
||||
The **ProGuard Gradle Plugin** is compatible with Android Gradle Plugin (AGP) versions 4.x - 7.x.
|
||||
|
||||
The **ProGuard** [keep rules configuration format](configuration/usage.md) is also supported by R8 (the default Android shrinker),
|
||||
so you can use your R8, ProGuard and DexGuard keep rules interchangeably.
|
||||
|
||||
See [Gradle Plugin setup](setup/gradleplugin.md) page for more information.
|
||||
|
||||
## Does ProGuard have support for Ant? {: #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.
|
||||
|
||||
See [Ant setup](setup/ant.md) page for more information.
|
||||
|
||||
## Does ProGuard have support for Java/Kotlin Gradle projects? {: #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.
|
||||
|
||||
See [Gradle setup](setup/gradle.md) page for more information.
|
||||
|
||||
## Does ProGuard have support for Maven? {: #maven}
|
||||
|
||||
While we don't officially provide a Maven integration and
|
||||
we cannot provide support there are solutions available,
|
||||
their offered functionality is not guaranteed by Guardsquare.
|
||||
|
||||
Some open-source implementations:
|
||||
|
||||
- [https://github.com/wvengen/proguard-maven-plugin](https://github.com/wvengen/proguard-maven-plugin)
|
||||
- [https://github.com/dingxin/proguard-maven-plugin](https://github.com/dingxin/proguard-maven-plugin)
|
||||
|
||||
## Does ProGuard come with a GUI? {: #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 `Class.forName` calls? {: #forname}
|
||||
|
||||
Yes. **ProGuard** automatically handles constructs like
|
||||
`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.
|
||||
|
||||
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
|
||||
"`(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? {: #resource}
|
||||
|
||||
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? {: #encrypt}
|
||||
|
||||
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**](http://www.guardsquare.com/dexguard), does provide string
|
||||
encryption, along with more protection techniques against static and dynamic
|
||||
analysis.
|
||||
|
||||
## Does ProGuard perform control flow obfuscation?
|
||||
|
||||
No. Control flow obfuscation injects additional branches into the bytecode, in
|
||||
an attempt to fool decompilers. **ProGuard** does not do this, except to some
|
||||
extent in its optimization techniques. **ProGuard**'s closed-source sibling
|
||||
for Android, [**DexGuard**](http://www.guardsquare.com/dexguard), does offer
|
||||
control flow obfuscation, as one of the many additional techniques to harden
|
||||
Android apps.
|
||||
|
||||
## Does ProGuard support incremental obfuscation? {: #incremental}
|
||||
|
||||
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? {: #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? {: #stacktrace}
|
||||
|
||||
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](manual/index.md) for more
|
||||
details.
|
||||
|
||||
## How is DexGuard different from ProGuard?
|
||||
|
||||
[**DexGuard**](http://www.guardsquare.com/dexguard) is a commercial extension
|
||||
of **ProGuard**:
|
||||
|
||||
- **DexGuard** is specialized for Android applications and libraries: it
|
||||
optimizes and obfuscates not just the bytecode, but also the manifest file,
|
||||
resources, resource files, asset files, and native libraries.
|
||||
- **DexGuard** focuses on making apps self-defending against reverse
|
||||
engineering and tampering. **DexGuard**'s techniques for obfuscation,
|
||||
encryption, and detection are a lot stronger than **ProGuard**'s basic name
|
||||
obfuscation.
|
||||
- **DexGuard** is backward compatible with **ProGuard**: it reads the same
|
||||
configuration. It already comes with tuned configuration for the Android
|
||||
runtime and for common Android libraries.
|
@ -1,71 +0,0 @@
|
||||
# Building ProGuard
|
||||
|
||||
!!! info
|
||||
|
||||
**ProGuard** is distributed under the terms of the GNU General Public License. Please consult the [license page](license/license.md) for more details.
|
||||
|
||||
Building ProGuard is easy - you'll need:
|
||||
|
||||
* a Java 8 JDK installed
|
||||
* a clone of the [ProGuard](https://github.com/Guardsquare/proguard.git) repository
|
||||
|
||||
You can then execute a composite build with the following Gradle command:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
./gradlew assemble
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```bash
|
||||
gradlew assemble
|
||||
```
|
||||
|
||||
|
||||
The artifacts will be generated in the `lib` directory. You can then execute ProGuard using the
|
||||
scripts in `bin`, for example:
|
||||
|
||||
=== "Linux/macOS"
|
||||
|
||||
```bash
|
||||
bin/proguard.sh
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
|
||||
```bash
|
||||
bin\proguard.bat
|
||||
```
|
||||
|
||||
## Publish to Maven local
|
||||
|
||||
|
||||
You can publish the artifacts to your local Maven cache (something like `~/.m2/`):
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
./gradlew publishToMavenLocal
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```bash
|
||||
gradlew publishToMavenLocal
|
||||
```
|
||||
|
||||
## Building a release distribution
|
||||
|
||||
You can build tar and zip archives with the binaries and documentation:
|
||||
|
||||
|
||||
=== "Linux/macOS"
|
||||
|
||||
```bash
|
||||
./gradlew distTar distZip
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
|
||||
```bash
|
||||
gradlew distTar distZip
|
||||
```
|
||||
|
@ -1,176 +0,0 @@
|
||||
Class files essentially define classes, their fields, and their methods. A lot
|
||||
of essential and non-essential data are attached to these classes, fields, and
|
||||
methods as *attributes*. For instance, attributes can contain bytecode, source
|
||||
file names, line number tables, etc.
|
||||
|
||||
ProGuard's obfuscation step removes attributes that are generally not
|
||||
necessary for executing the code. With the
|
||||
[`-keepattributes`](usage.md#keepattributes) option, you can specify a filter
|
||||
for attributes that you do want to keep, for instance if your code accesses
|
||||
them through reflection, or if you want to preserve some compilation or
|
||||
debugging information. The filter works like any [filter](usage.md#filters) in
|
||||
ProGuard.
|
||||
|
||||
The following wildcards are supported:
|
||||
|
||||
| Wildcard | Meaning
|
||||
|-----|----------------------------------------------------
|
||||
| `?` | matches any single character in an attribute name.
|
||||
| `*` | matches any part of an attribute name.
|
||||
|
||||
An attribute name that is preceded by an exclamation mark '**!**' is
|
||||
*excluded* from further attempts to match with *subsequent* attribute names in
|
||||
the filter. Make sure to specify filters correctly, since they are not checked
|
||||
for potential typos.
|
||||
|
||||
For example, the following setting preserves the optional attributes that are
|
||||
typically necessary when processing code that is intended to be used as a
|
||||
library:
|
||||
```proguard
|
||||
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
|
||||
SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
|
||||
```
|
||||
|
||||
The Java bytecode specifications currently specify the following list of
|
||||
attributes.
|
||||
|
||||
## Optional attributes
|
||||
|
||||
ProGuard's obfuscation step by default discards the following optional
|
||||
attributes. You can keep them with the
|
||||
[`-keepattributes`](usage.md#keepattributes) option.
|
||||
|
||||
`SourceFile`
|
||||
: Specifies the name of the source file from which the class file was
|
||||
compiled. If present, this name is reported in stack traces.
|
||||
|
||||
`SourceDir`<div>(J++ extension)</div>
|
||||
: Specifies the name of the source directory from which the class file was
|
||||
compiled.
|
||||
|
||||
`Record` <div>(Java 14 or higher)</div>
|
||||
: Specifies the components of a record class. Code may access this information
|
||||
by reflection.
|
||||
|
||||
`InnerClasses`
|
||||
: Specifies the relationship between a class and its inner classes and outer
|
||||
classes. Other than this and the naming convention with a '\$' separator
|
||||
between the names of inner classes and outer classes, inner classes are just
|
||||
like ordinary classes. Compilers may need this information to find classes
|
||||
referenced in a compiled library. Code may access this information by
|
||||
reflection, for instance to derive the simple name of the class.
|
||||
|
||||
`PermittedSubclasses` <div>(Java 15 or higher)</div>
|
||||
: Specifies the allowed extensions or implementations of sealed classes or
|
||||
interfaces.
|
||||
|
||||
`EnclosingMethod`<div>(Java 5 or higher)</div>
|
||||
: Specifies the method in which the class was defined. Compilers may need this
|
||||
information to find classes referenced in a compiled library. Code may
|
||||
access this information by reflection, for instance to derive the simple
|
||||
name of the class.
|
||||
|
||||
`Deprecated`
|
||||
: Indicates that the class, field, or method is deprecated.
|
||||
|
||||
`Synthetic`
|
||||
: Indicates that the class, field, or method was generated by the compiler.
|
||||
|
||||
`Signature`<div>(Java 5 or higher)</div>
|
||||
: Specifies the generic signature of the class, field, or method. Compilers
|
||||
may need this information to properly compile classes that use generic types
|
||||
from compiled libraries. Code may access this signature by reflection.
|
||||
|
||||
`MethodParameters`<div>(Java 8 or higher)</div>
|
||||
: Specifies the names and access flags of the parameters of the method. Code
|
||||
may access this information by reflection.
|
||||
|
||||
`Exceptions`
|
||||
: Specifies the exceptions that a method may throw. Compilers may use this
|
||||
information to enforce catching them.
|
||||
|
||||
`LineNumberTable`
|
||||
: Specifies the line numbers of the method. If present, these line numbers are
|
||||
reported in stack traces.
|
||||
|
||||
`LocalVariableTable`
|
||||
: Specifies the names and types of local variables of the method. If present,
|
||||
some IDEs may use this information for helping with auto-completion.
|
||||
|
||||
`LocalVariableTypeTable`<div>(Java 5 or higher)</div>
|
||||
: Specifies the names and generic types of local variables of the method. If
|
||||
present, some IDEs may use this information for helping with
|
||||
auto-completion.
|
||||
|
||||
`RuntimeVisibleAnnotations`<div>(Java 5 or higher)</div>
|
||||
: Specifies the annotations that are visible at run-time, for classes, fields,
|
||||
and methods. Compilers and annotation processors may use these annotations.
|
||||
Code may access them by reflection.
|
||||
|
||||
`RuntimeInvisibleAnnotations`<div>(Java 5 or higher)</div>
|
||||
|
||||
: Specifies the annotations that are visible at compile-time, for classes,
|
||||
fields, and methods. Compilers and annotation processors may use these
|
||||
annotations.
|
||||
|
||||
`RuntimeVisibleParameterAnnotations`<div>(Java 5 or higher)</div>
|
||||
|
||||
: Specifies the annotations that are visible at run-time, for method
|
||||
parameters. Compilers and annotation processors may use these annotations.
|
||||
Code may access them by reflection.
|
||||
|
||||
`RuntimeInvisibleParameterAnnotations`<div>(Java 5 or higher)</div>
|
||||
|
||||
: Specifies the annotations that are visible at compile-time, for method
|
||||
parameters. Compilers and annotation processors may use these annotations.
|
||||
|
||||
`RuntimeVisibleTypeAnnotations`<div>(Java 8 or higher)</div>
|
||||
: Specifies the annotations that are visible at run-time, for generic types,
|
||||
instructions, etc. Compilers and annotation processors may use these
|
||||
annotations. Code may access them by reflection.
|
||||
|
||||
`RuntimeInvisibleTypeAnnotations`<div>(Java 8 or higher)</div>
|
||||
|
||||
: Specifies the annotations that are visible at compile-time, for generic
|
||||
types, instructions, etc. Compilers and annotation processors may use these
|
||||
annotations.
|
||||
|
||||
`AnnotationDefault`<div>(Java 5 or higher)</div>
|
||||
: Specifies a default value for an annotation.
|
||||
|
||||
## Essential attributes
|
||||
|
||||
ProGuard automatically keeps the following essential attributes, processing
|
||||
them as necessary. We're listing them for the sake of completeness:
|
||||
|
||||
`ConstantValue`
|
||||
: Specifies a constant integer, float, class, string, etc.
|
||||
|
||||
`Code`
|
||||
: Specifies the actual bytecode of a method.
|
||||
|
||||
`StackMap`<div>(Java Micro Edition)</div>
|
||||
: Provides preverification information. The Java Virtual Machine can use this
|
||||
information to speed up the verification step when loading a class.
|
||||
|
||||
`StackMapTable`<div>(Java 6 or higher)</div>
|
||||
: Provides preverification information. The Java Virtual Machine can use this
|
||||
information to speed up the verification step when loading a class.
|
||||
|
||||
`BootstrapMethods`<div>(Java 7 or higher)</div>
|
||||
: Specifies the methods to bootstrap dynamic method invocations.
|
||||
|
||||
`Module`<div>(Java 9 or higher)</div>
|
||||
: Specifies the dependencies of a _module_.
|
||||
|
||||
`ModuleMainClass`<div>(Java 9 or higher)</div>
|
||||
: Specifies the main class of a _module_.
|
||||
|
||||
`ModulePackages`<div>(Java 9 or higher)</div>
|
||||
: Specifies the packages of a _module_.
|
||||
|
||||
`NestHost`<div>(Java 11 or higher)</div>
|
||||
: Specifies the host class of a _nest_, for example an outer class.
|
||||
|
||||
`NestMembers`<div>(Java 11 or higher)</div>
|
||||
: Specifies the members of a _nest_, for example the inner classes.
|
File diff suppressed because it is too large
Load Diff
@ -1,221 +0,0 @@
|
||||
The optimization step of ProGuard can be switched off with the
|
||||
[`-dontoptimize`](usage.md#dontoptimize) option. For more fine-grained
|
||||
control over individual optimizations, experts can use the
|
||||
[`-optimizations`](usage.md#optimizations) option, with a filter based
|
||||
on the optimization names listed below. The filter works like any
|
||||
[filter](usage.md#filters) in ProGuard.
|
||||
|
||||
The following wildcards are supported:
|
||||
|
||||
| Wildcard | Meaning
|
||||
|-----|-------------------------------------------------------
|
||||
| `?` | matches any single character in an optimization name.
|
||||
| `*` | matches any part of an optimization name.
|
||||
|
||||
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.
|
||||
|
||||
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 for newer versions, as
|
||||
optimizations are added and reorganized.
|
||||
|
||||
`library/gson`
|
||||
: Optimizes usages of the Gson library, whenever possible. See [Gson
|
||||
optimization](optimizations.md#gson) for more details.
|
||||
|
||||
`class/marking/final`
|
||||
: Marks classes as final, whenever possible.
|
||||
|
||||
`class/unboxing/enum`
|
||||
: Simplifies enum types to integer constants, 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.
|
||||
|
||||
`class/merging/wrapper`
|
||||
: Merges wrapper classes with their wrapped classes, whenever possible.
|
||||
|
||||
`field/removal/writeonly`<div>(⇒ `code/removal/advanced`)</div>
|
||||
: Removes write-only fields.
|
||||
|
||||
`field/marking/private`
|
||||
: Marks fields as private, whenever possible.
|
||||
|
||||
`field/generalization/class`
|
||||
: Generalizes the classes of field accesses, whenever possible.
|
||||
|
||||
`field/specialization/type`
|
||||
: Specializes the types of fields, whenever possible
|
||||
|
||||
`field/propagation/value`<div>(⇒ `code/simplification/advanced`)</div>
|
||||
: Propagates the values of fields across methods.
|
||||
|
||||
`method/marking/private`
|
||||
: Marks methods as private, whenever possible (*devirtualization*).
|
||||
|
||||
`method/marking/static`<div>(⇒ `code/removal/advanced`)</div>
|
||||
: Marks methods as static, whenever possible (*devirtualization*).
|
||||
|
||||
`method/marking/final`
|
||||
: Marks methods as final, whenever possible.
|
||||
|
||||
`method/marking/synchronized`
|
||||
: Unmarks methods as synchronized, whenever possible.
|
||||
|
||||
`method/removal/parameter`<div>(⇒ `code/removal/advanced`)</div>
|
||||
: Removes unused method parameters.
|
||||
|
||||
`method/generalization/class`
|
||||
: Generalizes the classes of method invocations, whenever possible.
|
||||
|
||||
`method/specialization/parametertype`
|
||||
: Specializes the types of method parameters, whenever possible.
|
||||
|
||||
`method/specialization/returntype`
|
||||
: Specializes the types of method return values, whenever possible.
|
||||
|
||||
`method/propagation/parameter`<div>(⇒ `code/simplification/advanced`)</div>
|
||||
: Propagates the values of method parameters from method invocations to the
|
||||
invoked methods.
|
||||
|
||||
`method/propagation/returnvalue`<div>(⇒ `code/simplification/advanced`)</div>
|
||||
: 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/simplification/branch`<div>(⇒ `code/removal/simple`)</div>
|
||||
: Performs peephole optimizations for branch instructions.
|
||||
|
||||
`code/simplification/object`
|
||||
: Performs peephole optimizations for object instantiation.
|
||||
|
||||
`code/simplification/string`
|
||||
: Performs peephole optimizations for constant strings.
|
||||
|
||||
`code/simplification/math`
|
||||
: Performs peephole optimizations for Math method calls.
|
||||
|
||||
`code/simplification/advanced`<div>(*best used with* `code/removal/advanced`)</div>
|
||||
: Simplifies code based on control flow analysis and data flow analysis.
|
||||
|
||||
`code/removal/advanced`<div>(⇒ `code/removal/exception`)</div>
|
||||
: Removes dead code based on control flow analysis and data flow analysis.
|
||||
|
||||
`code/removal/simple`<div>(⇒ `code/removal/exception`)</div>
|
||||
: 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.
|
||||
|
||||
## Aggressive optimization
|
||||
|
||||
ProGuard provides the `-optimizeaggressively` option. If set, this enables more
|
||||
aggressive assumptions during optimization. This might lead to
|
||||
improved performance and/or reduced code size, but might result in different behavior in rare cases.
|
||||
For example, reading from an array might cause an
|
||||
`ArrayIndexOutOfBoundsException` to be thrown. Strictly speaking, this means
|
||||
that such an instruction can have a side effect. If this instruction is removed
|
||||
during optimization, the code will thus behave differently under specific
|
||||
circumstances. By default, such instructions are always preserved. Setting this
|
||||
option will lead to these instructions being candidates for removal during
|
||||
optimization. Additionally, class merging is only enabled when this option is set.
|
||||
|
||||
## Gson optimization {: #gson}
|
||||
|
||||
ProGuard optimizes Gson code by detecting which domain classes are serialized
|
||||
using the Gson library. It replaces the reflection-based implementation of
|
||||
GSON for reading and writing fields with injected and optimized code that
|
||||
accesses the fields of the domain classes directly when reading and writing
|
||||
JSON. The benefits of this optimization are the following:
|
||||
|
||||
- Domain classes used in conjunction with GSON can be freely obfuscated.
|
||||
- The injected serialization code gives better performance compared to the
|
||||
GSON implementation, which relies on reflection.
|
||||
- Less configuration is needed as the optimization automatically keeps classes
|
||||
and fields that are required for serialization.
|
||||
|
||||
### Configuration
|
||||
|
||||
The Gson optimization is enabled by default and doesn't require any additional
|
||||
configuration, as long as the application code doesn't use unsupported Gson
|
||||
features(see [Known limitations](optimizations.md#gsonlimitations)).
|
||||
|
||||
### Known limitations {: #gsonlimitations}
|
||||
|
||||
ProGuard can not optimize the following use cases of Gson:
|
||||
|
||||
- Serializing classes containing one of the following Gson annotations:
|
||||
- `@JsonAdapter`
|
||||
- `@Since`
|
||||
- `@Until`
|
||||
- Serializing classes that have generic type variables in their signature.
|
||||
- Serializing classes using a Gson instance that was built with one of the
|
||||
following settings on the GsonBuilder:
|
||||
- `excludeFieldsWithModifier`
|
||||
- `setFieldNamingPolicy`
|
||||
|
||||
When one of the above Gson features is used, ProGuard automatically preserves
|
||||
the original Gson implementation for all affected domain classes.
|
||||
|
||||
This means that the serialized fields of these domain classes need to be
|
||||
explicitly kept again in the ProGuard configuration so that they can be
|
||||
safely accessed through reflection.
|
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
By now, we'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 us know.
|
||||
|
||||
At [Guardsquare](http://www.guardsquare.com/), we develop ProGuard and its
|
||||
professional siblings DexGuard (for Android) and iXGuard (for iOS). If you
|
||||
find ProGuard useful and you are interested in more features or professional
|
||||
support, this is the place to go.
|
||||
|
||||
ProGuard is currently hosted on GitHub:
|
||||
|
||||
- You can report issues on our
|
||||
[issue tracker](https://github.com/Guardsquare/proguard/issues).
|
||||
|
||||
- You can clone the
|
||||
[source code](https://github.com/Guardsquare/proguard) yourself and create
|
||||
[pull requests](https://github.com/Guardsquare/proguard/pulls).
|
||||
|
||||
!!! tip
|
||||
The [***Guardsquare Community***](https://community.guardsquare.com/) is the place to be for all your ProGuard-related questions and feedback.
|
||||
|
||||
You may also find answers on
|
||||
[Stack Overflow](http://stackoverflow.com/questions/tagged/proguard).
|
||||
|
||||
ProGuard used to be hosted on Sourceforge:
|
||||
|
||||
- You can still read answers in the [help
|
||||
forum](https://sourceforge.net/projects/proguard/forums/forum/182456).
|
||||
|
||||
- You can still find discussions in the [open discussion
|
||||
forum](https://sourceforge.net/projects/proguard/forums/forum/182455).
|
||||
|
||||
- We still have reports on the
|
||||
[bug tracking page](http://sourceforge.net/p/proguard/bugs/).
|
||||
|
||||
- We still have new ideas on the the
|
||||
[feature request page](http://sourceforge.net/p/proguard/feature-requests/).
|
||||
|
||||
- You can still find all earlier versions in the
|
||||
[download section](https://sourceforge.net/projects/proguard/files/).
|
@ -1,126 +0,0 @@
|
||||
Welcome to the manual for **ProGuard** version 7.3 ([what's new?](releasenotes.md)).
|
||||
|
||||
ProGuard is an open-sourced Java class file shrinker, optimizer, obfuscator, and
|
||||
preverifier. As a result, ProGuard processed applications and libraries are smaller and faster.
|
||||
|
||||
- The ***shrinking step*** detects and removes unused classes, fields, methods, and
|
||||
attributes.
|
||||
- The ***optimizer step*** optimizes bytecode and removes unused instructions.
|
||||
- The ***name obfuscation step*** renames the remaining classes, fields, and methods using short meaningless names.
|
||||
- The final ***preverification step*** adds preverification information to the classes, which is required for Java Micro Edition and for Java 6 and higher.
|
||||
|
||||
The default Android shrinker, R8, is compatible with ProGuard [configuration](configuration/usage.md).
|
||||
|
||||
If you are getting started with ProGuard, please follow the [Quick Start](building.md) guide in order to arrive at a basic setup for your application or library as quickly as possible.
|
||||
|
||||
Experienced users can directly consult the [Configuration section](configuration/usage.md) where all features are described.
|
||||
|
||||
If during the process you run into any issues, please make sure to check the [Troubleshooting section](troubleshooting/troubleshooting.md).
|
||||
|
||||
## How it works
|
||||
|
||||
<div class="center">
|
||||
<div class="diagram">
|
||||
<div class="row">
|
||||
<div class="green box">Input jars</div>
|
||||
<div class="right arrow">shrink</div>
|
||||
<div class="right arrow">optimize</div>
|
||||
<div class="right arrow">obfuscate</div>
|
||||
<div class="right arrow">preverify</div>
|
||||
<div class="green box">Output jars</div>
|
||||
</div>
|
||||
<div class="distributed">
|
||||
<div class="green box">Library jars</div>
|
||||
<div class="right arrow">(unchanged)</div>
|
||||
<div class="green box">Library jars</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
ProGuard first reads the **input jars** (or aars, wars, ears, zips, apks, 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 aars, wars, ears, zips, apks, 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 aars, wars, ears, zips, apks, 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 **name 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](configuration/usage.md) of this manual describes the necessary [`-keep`
|
||||
options](configuration/usage.md#keepoptions) and the [Examples section](configuration/examples.md)
|
||||
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`](configuration/usage.md#keep)
|
||||
options.
|
||||
|
||||
However, ProGuard already detects and handles the following cases for you:
|
||||
|
||||
- `Class.forName("SomeClass")`
|
||||
- `SomeClass.class`
|
||||
- `SomeClass.class.getField("someField")`
|
||||
- `SomeClass.class.getDeclaredField("someField")`
|
||||
- `SomeClass.class.getMethod("someMethod", null)`
|
||||
- `SomeClass.class.getMethod("someMethod", new Class[] { A.class,... })`
|
||||
- `SomeClass.class.getDeclaredMethod("someMethod", null)`
|
||||
- `SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class,... })`
|
||||
- `AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")`
|
||||
- `AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")`
|
||||
- `AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")`
|
||||
|
||||
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.
|
||||
|
||||
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 interface `SomeClass` and/or its
|
||||
implementations may need to be preserved. You can then adapt your
|
||||
configuration accordingly.
|
||||
|
||||
!!! tip
|
||||
Generate an instrumented build to allow ProGuard finding cases of reflection at *run-time*. The tailored configuration advice for your application will be outputted to the console, and can be copy/pasted to your configuration. To do so, just enable the option [`-addconfigurationdebugging`](configuration/usage.md#addconfigurationdebugging)
|
||||
|
||||
|
||||
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.
|
@ -1,6 +0,0 @@
|
||||
## Java language support
|
||||
|
||||
!!! Warning
|
||||
ProGuard no longer supports backporting, and cannot backport class files compiled with Java >11.
|
||||
|
||||
Provide supports Java versions up to and including 19.
|
@ -1,83 +0,0 @@
|
||||
The Kotlin compiler injects code and metadata into the classes that it generates to support features not natively supported by the Java and Android environments. The metadata injected by the Kotlin compiler takes the shape of an annotation added to classes which leaks semantic information that can aid attackers.
|
||||
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
In most cases, you do not need to keep Kotlin metadata for app projects - therefore, no configuration changes are necessary and the Kotlin metadata can be safely removed.
|
||||
However, there are two common reasons to explicitly keep the metadata, [reflection](#reflection) and [libraries](#library-projects).
|
||||
|
||||
ProGuard will only keep the Kotlin metadata of a class if you explicitly keep that class or one of its members, and you add the `-keep class kotlin.Metadata` option to your configuration.
|
||||
Note that this option may also be required by an SDK of your project, and indirectly added as a consumer rule.
|
||||
|
||||
For example, if you have the following keep rule for a Kotlin class named `com.example.KotlinExample`, by default the class will be kept but its metadata will not:
|
||||
|
||||
```
|
||||
# Keep the class com.example.KotlinExample
|
||||
-keep class com.example.KotlinExample
|
||||
```
|
||||
|
||||
You can add `-keep class kotlin.Metadata` to your configuration to instruct ProGuard to keep and adapt Kotlin metadata:
|
||||
|
||||
```
|
||||
# Add this option to tell ProGuard to keep and adapt Kotlin metadata
|
||||
-keep class kotlin.Metadata
|
||||
```
|
||||
|
||||
|
||||
### App Projects
|
||||
|
||||
|
||||
The most common case to keep Kotlin metadata would be if you use the [kotlin-reflect](https://kotlinlang.org/docs/reference/reflection.html) library. Just like when using Java reflection, you will need `-keep` rules in your configuration to keep the specific classes and members accessed through reflection.
|
||||
|
||||
In this case, to instruct ProGuard to keep and adapt the corresponding Kotlin metadata, add the following to your configuration:
|
||||
|
||||
```
|
||||
-keep class kotlin.Metadata
|
||||
```
|
||||
|
||||
A popular framework that relies on reflection is [Jackson](https://github.com/FasterXML/jackson-module-kotlin).
|
||||
|
||||
### Library Projects
|
||||
|
||||
When developing an SDK that exposes Kotlin-specific features to its users, you need to preserve the metadata of the public API.
|
||||
These include features such as named parameters, suspend functions, top-level functions and type aliases.
|
||||
|
||||
In the case of a library, you would already be keeping the public API, so you can simply add the following
|
||||
to your configuration:
|
||||
|
||||
```
|
||||
-keep class kotlin.Metadata
|
||||
```
|
||||
|
||||
## Protection
|
||||
|
||||
### Obfuscation
|
||||
|
||||
ProGuard will apply the same obfuscations to Kotlin identifiers in metadata, such as class or member names, to match those in the Java class files.
|
||||
This ensures that, even where the Kotlin metadata is required, no sensitive names remain in the metadata.
|
||||
|
||||
### Shrinking
|
||||
|
||||
ProGuard will remove all unused Kotlin metadata components such as unused functions and properties.
|
||||
This ensures that, even where the Kotlin metadata is required, only the used components are kept.
|
||||
|
||||
|
||||
|
||||
### Data Classes
|
||||
|
||||
Data classes in Kotlin have an auto-generated `toString` method that lists all properties
|
||||
of the class and their value. ProGuard automatically detects these classes and adapts
|
||||
the names of properties to their obfuscated counterpart.
|
||||
|
||||
### Intrinsics Null Checks
|
||||
|
||||
To better support java interoperability, Kotlin injects numerous method calls to e.g.
|
||||
check that a parameter is not null when it wasn't marked as `Nullable`. In pure Kotlin
|
||||
codebases, these injected method calls are unnecessary and instead leak information
|
||||
via their parameters (e.g. names of checked parameters).
|
||||
|
||||
ProGuard automatically detects calls to these methods and removes the Strings to
|
||||
ensure that the resulting code contains no references to original parameter names, member names etc.
|
||||
|
||||
|
@ -1,259 +0,0 @@
|
||||
# GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
## TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
**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:
|
||||
|
||||
- **a)** You must cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
- **b)** You must cause any work that you distribute or publish, that in whole
|
||||
or in part contains or is derived from the Program or any part thereof, to
|
||||
be licensed as a whole at no charge to all third parties under the terms of
|
||||
this License.
|
||||
- **c)** If the modified program normally reads commands interactively when
|
||||
run, you must cause it, when started running for such interactive use in the
|
||||
most ordinary way, to print or display an announcement including an
|
||||
appropriate copyright notice and a notice that there is no warranty (or
|
||||
else, saying that you provide a warranty) and that users may redistribute
|
||||
the program under these conditions, and telling the user how to view a copy
|
||||
of this License. (Exception: if the Program itself is interactive but does
|
||||
not normally print such an announcement, your work based on the Program is
|
||||
not required to print an announcement.)
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
- **a)** Accompany it with the complete corresponding machine-readable source
|
||||
code, which must be distributed under the terms of Sections 1 and 2 above on
|
||||
a medium customarily used for software interchange; or,
|
||||
- **b)** Accompany it with a written offer, valid for at least three years, to
|
||||
give any third party, for a charge no more than your cost of physically
|
||||
performing source distribution, a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
- **c)** Accompany it with the information you received as to the offer to
|
||||
distribute corresponding source code. (This alternative is allowed only for
|
||||
noncommercial distribution and only if you received the program in object
|
||||
code or executable form with such an offer, in accord with Subsection b
|
||||
above.)
|
||||
|
||||
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.
|
||||
|
||||
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.
|
@ -1,36 +0,0 @@
|
||||
# Special Exception to the GNU General Public License
|
||||
|
||||
Copyright © 2002-2020 Guardsquare NV
|
||||
|
||||
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, Guardsquare NV gives permission to link
|
||||
the code of this program with the following stand-alone applications:
|
||||
|
||||
- Gradle,
|
||||
- Apache Ant,
|
||||
- Apache Maven,
|
||||
- the Google Android SDK,
|
||||
- the Intel TXE/DAL SDK,
|
||||
- the Eclipse ProGuardDT GUI,
|
||||
- the EclipseME JME IDE,
|
||||
- the Oracle NetBeans Java IDE,
|
||||
- the Oracle JME Wireless Toolkit, and
|
||||
- the Simple Build Tool for Scala (and its scripts).
|
||||
|
||||
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.
|
@ -1,26 +0,0 @@
|
||||
**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 unchanged.
|
||||
|
||||
The **ProGuard code** 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.md) (GPL), version 2, as published by
|
||||
the [Free Software Foundation](http://www.fsf.org/) (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.
|
||||
|
||||
We are granting a [special exception](gplexception.md) to the latter clause
|
||||
(in wording suggested by the
|
||||
[FSF](http://www.gnu.org/copyleft/gpl-faq.html#GPLIncompatibleLibs)), for
|
||||
combinations with the following stand-alone applications: Gradle, Apache Ant,
|
||||
Apache Maven, the Google Android SDK, the Intel TXE/DAL SDK, the Eclipse
|
||||
ProGuardDT GUI, the EclipseME JME IDE, the Oracle NetBeans Java IDE, the
|
||||
Oracle JME Wireless Toolkit, and the Simple Build Tool for Scala.
|
||||
|
||||
The **ProGuard user documentation** is copyrighted as well. It may only
|
||||
be redistributed without changes, along with the unmodified version of
|
||||
the code.
|
@ -1,78 +0,0 @@
|
||||
# Quick Start
|
||||
|
||||
This page will guide you through the basic steps of processing your application or library with ProGuard.
|
||||
For details on advanced settings or more background information please refer to the relevant parts of the manual.
|
||||
|
||||
|
||||
There are two ways to execute ProGuard:
|
||||
|
||||
1. Standalone
|
||||
2. Integrated mode in your Gradle, Ant or Maven project.
|
||||
|
||||
You can also build ProGuard from [source](https://github.com/Guardsquare/proguard) by following the [build instructions](building.md).
|
||||
|
||||
## Standalone
|
||||
|
||||
Firstly, download a [ProGuard release](https://github.com/Guardsquare/proguard/releases) or [build ProGuard](building.md) from source.
|
||||
ProGuard can then be executed directly from the command line by calling a script found in the `bin` directory:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
bin/proguard.sh -injars path/to/my-application.jar \
|
||||
-outjars path/to/obfuscated-application.jar \
|
||||
-libraryjars path/to/java/home/lib/rt.jar
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```bat
|
||||
bin\proguard.bat -injars path/to/my-application.jar ^
|
||||
-outjars path/to/obfuscated-application.jar ^
|
||||
-libraryjars path/to/java/home/lib/rt.jar
|
||||
```
|
||||
|
||||
For more detailed information see [standalone mode](setup/standalone.md).
|
||||
|
||||
## Integrated
|
||||
|
||||
The ProGuard artifacts are hosted at [Maven Central](https://search.maven.org/search?q=g:com.guardsquare).
|
||||
|
||||
### Android Gradle project
|
||||
|
||||
When working on your Android application (apk, aab) or library (aar), you can include ProGuard in your Gradle build by:
|
||||
|
||||
- Using ProGuard's Gradle plugin, which you can apply in your `build.gradle` file (AGP 4.x - 7.x).
|
||||
- Using the integrated ProGuard by disabling R8 in your `gradle.properties` (only applicable for AGP < 7).
|
||||
|
||||
For more detailed information see [Android Gradle](setup/gradleplugin.md).
|
||||
|
||||
### Java or Kotlin Gradle project
|
||||
|
||||
Your non-mobile Java or Kotlin applications can execute ProGuard's Gradle task:
|
||||
```proguard
|
||||
task myProguardTask(type: proguard.gradle.ProGuardTask) {
|
||||
.....
|
||||
}
|
||||
```
|
||||
|
||||
For more detailed information see [Java/Kotlin Gradle](setup/gradle.md).
|
||||
|
||||
### Ant project
|
||||
|
||||
You can also include ProGuard in your Ant build, all you have to do is to include the related task into your `build.xml` file:
|
||||
```xml
|
||||
<taskdef resource="proguard/ant/task.properties"
|
||||
classpath="/usr/local/java/proguard/lib/proguard.jar" />
|
||||
```
|
||||
|
||||
For more detailed information see [Ant](setup/ant.md).
|
||||
|
||||
|
||||
### Maven project
|
||||
|
||||
!!! warning
|
||||
While we don't officially provide a maven integration and we cannot provide support there are solutions available, their offered functionality is not guaranteed by Guardsquare.
|
||||
|
||||
Some open-source implementations:
|
||||
|
||||
- [https://github.com/wvengen/proguard-maven-plugin](https://github.com/wvengen/proguard-maven-plugin)
|
||||
- [https://github.com/dingxin/proguard-maven-plugin](https://github.com/dingxin/proguard-maven-plugin)
|
@ -1,141 +0,0 @@
|
||||
## Usage
|
||||
|
||||
| OS | Command
|
||||
|------------|-----------------------------
|
||||
| Windows: | `proguard` *options* ...
|
||||
| Linux/Mac: | `proguard.sh` *options* ...
|
||||
|
||||
Typically:
|
||||
|
||||
| OS | Command
|
||||
|------------|-----------------------------
|
||||
| Windows: | `proguard @myconfig.pro`
|
||||
| Linux/Mac: | `proguard.sh @myconfig.pro`
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Meaning
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------
|
||||
| [`@`](configuration/usage.md#at)[*filename*](configuration/usage.md#filename) | Short for '`-include` *filename*'.
|
||||
| [`-include`](configuration/usage.md#include) [*filename*](configuration/usage.md#filename) | Read configuration options from the given file.
|
||||
| [`-basedirectory`](configuration/usage.md#basedirectory) [*directoryname*](configuration/usage.md#filename) | Specifies the base directory for subsequent relative file names.
|
||||
| [`-injars`](configuration/usage.md#injars) [*class\_path*](configuration/usage.md#classpath) | Specifies the program jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories).
|
||||
| [`-outjars`](configuration/usage.md#outjars) [*class\_path*](configuration/usage.md#classpath) | Specifies the names of the output jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories).
|
||||
| [`-libraryjars`](configuration/usage.md#libraryjars) [*class\_path*](configuration/usage.md#classpath) | Specifies the library jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories).
|
||||
| [`-skipnonpubliclibraryclasses`](configuration/usage.md#skipnonpubliclibraryclasses) | Ignore non-public library classes.
|
||||
| [`-dontskipnonpubliclibraryclasses`](configuration/usage.md#dontskipnonpubliclibraryclasses) | Don't ignore non-public library classes (the default).
|
||||
| [`-dontskipnonpubliclibraryclassmembers`](configuration/usage.md#dontskipnonpubliclibraryclassmembers) | Don't ignore package visible library class members.
|
||||
| [`-keepdirectories`](configuration/usage.md#keepdirectories) \[[*directory\_filter*](configuration/usage.md#filters)\] | Keep the specified directories in the output jars (or wars, ears, zips, or directories).
|
||||
| [`-target`](configuration/usage.md#target) *version* | **deprecated** Set the given version number in the processed classes.
|
||||
| [`-forceprocessing`](configuration/usage.md#forceprocessing) | Process the input, even if the output seems up to date.
|
||||
| [`-keep`](configuration/usage.md#keep) \[[,*modifier*](configuration/usage.md#keepoptionmodifiers),...\] [*class\_specification*](configuration/usage.md#classspecification) | Preserve the specified classes *and* class members.
|
||||
| [`-keepclassmembers`](configuration/usage.md#keepclassmembers) \[[,*modifier*](configuration/usage.md#keepoptionmodifiers),...\] [*class\_specification*](configuration/usage.md#classspecification) | Preserve the specified class members, if their classes are preserved as well.
|
||||
| [`-keepclasseswithmembers`](configuration/usage.md#keepclasseswithmembers) \[[,*modifier*](configuration/usage.md#keepoptionmodifiers),...\] [*class\_specification*](configuration/usage.md#classspecification) | Preserve the specified classes *and* class members, if all of the specified class members are present.
|
||||
| [`-keepnames`](configuration/usage.md#keepnames) [*class\_specification*](configuration/usage.md#classspecification) | Preserve the names of the specified classes *and* class members (if they aren't removed in the shrinking step).
|
||||
| [`-keepclassmembernames`](configuration/usage.md#keepclassmembernames) [*class\_specification*](configuration/usage.md#classspecification) | Preserve the names of the specified class members (if they aren't removed in the shrinking step).
|
||||
| [`-keepclasseswithmembernames`](configuration/usage.md#keepclasseswithmembernames) [*class\_specification*](configuration/usage.md#classspecification) | Preserve the names of the specified classes *and* class members, if all of the specified class members are present (after the shrinking step).
|
||||
| [`-if`](configuration/usage.md#if) [*class\_specification*](configuration/usage.md#classspecification) | Specify classes and class members that must be present to activate the subsequent `keep` option.
|
||||
| [`-printseeds`](configuration/usage.md#printseeds) \[[*filename*](configuration/usage.md#filename)\] | List classes and class members matched by the various [`-keep`](configuration/usage.md#keep) options, to the standard output or to the given file.
|
||||
| [`-dontshrink`](configuration/usage.md#dontshrink) | Don't shrink the input class files.
|
||||
| [`-printusage`](configuration/usage.md#printusage) \[[*filename*](configuration/usage.md#filename)\] | List dead code of the input class files, to the standard output or to the given file.
|
||||
| [`-whyareyoukeeping`](configuration/usage.md#whyareyoukeeping) [*class\_specification*](configuration/usage.md#classspecification) | Print details on why the given classes and class members are being kept in the shrinking step.
|
||||
| [`-dontoptimize`](configuration/usage.md#dontoptimize) | Don't optimize the input class files.
|
||||
| [`-optimizations`](configuration/usage.md#optimizations) [*optimization\_filter*](configuration/optimizations.md) | The optimizations to be enabled and disabled.
|
||||
| [`-optimizationpasses`](configuration/usage.md#optimizationpasses) *n* | The number of optimization passes to be performed.
|
||||
| [`-assumenosideeffects`](configuration/usage.md#assumenosideeffects) [*class\_specification*](configuration/usage.md#classspecification) | Assume that the specified methods don't have any side effects, while optimizing.
|
||||
| [`-assumenoexternalsideeffects`](configuration/usage.md#assumenoexternalsideeffects) [*class\_specification*](configuration/usage.md#classspecification) | Assume that the specified methods don't have any external side effects, while optimizing.
|
||||
| [`-assumenoescapingparameters`](configuration/usage.md#assumenoescapingparameters) [*class\_specification*](configuration/usage.md#classspecification) | Assume that the specified methods don't let any reference parameters escape to the heap, while optimizing.
|
||||
| [`-assumenoexternalreturnvalues`](configuration/usage.md#assumenoexternalreturnvalues) [*class\_specification*](configuration/usage.md#classspecification) | Assume that the specified methods don't return any external reference values, while optimizing.
|
||||
| [`-assumevalues`](configuration/usage.md#assumevalues) [*class\_specification*](configuration/usage.md#classspecification) | Assume fixed values or ranges of values for primitive fields and methods, while optimizing.
|
||||
| [`-allowaccessmodification`](configuration/usage.md#allowaccessmodification) | Allow the access modifiers of classes and class members to be modified, while optimizing.
|
||||
| [`-mergeinterfacesaggressively`](configuration/usage.md#mergeinterfacesaggressively) | Allow any interfaces to be merged, while optimizing.
|
||||
| [`-dontobfuscate`](configuration/usage.md#dontobfuscate) | Don't obfuscate the input class files.
|
||||
| [`-printmapping`](configuration/usage.md#printmapping) \[[*filename*](configuration/usage.md#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`](configuration/usage.md#applymapping) [*filename*](configuration/usage.md#filename) | Reuse the given mapping, for incremental obfuscation.
|
||||
| [`-obfuscationdictionary`](configuration/usage.md#obfuscationdictionary) [*filename*](configuration/usage.md#filename) | Use the words in the given text file as obfuscated field names and method names.
|
||||
| [`-classobfuscationdictionary`](configuration/usage.md#classobfuscationdictionary) [*filename*](configuration/usage.md#filename) | Use the words in the given text file as obfuscated class names.
|
||||
| [`-packageobfuscationdictionary`](configuration/usage.md#packageobfuscationdictionary) [*filename*](configuration/usage.md#filename) | Use the words in the given text file as obfuscated package names.
|
||||
| [`-overloadaggressively`](configuration/usage.md#overloadaggressively) | Apply aggressive overloading while obfuscating.
|
||||
| [`-useuniqueclassmembernames`](configuration/usage.md#useuniqueclassmembernames) | Ensure uniform obfuscated class member names for subsequent incremental obfuscation.
|
||||
| [`-dontusemixedcaseclassnames`](configuration/usage.md#dontusemixedcaseclassnames) | Don't generate mixed-case class names while obfuscating.
|
||||
| [`-keeppackagenames`](configuration/usage.md#keeppackagenames) \[*[package\_filter](configuration/usage.md#filters)*\] | Keep the specified package names from being obfuscated.
|
||||
| [`-flattenpackagehierarchy`](configuration/usage.md#flattenpackagehierarchy) \[*package\_name*\] | Repackage all packages that are renamed into the single given parent package.
|
||||
| [`-repackageclasses`](configuration/usage.md#repackageclasses) \[*package\_name*\] | Repackage all class files that are renamed into the single given package.
|
||||
| [`-keepattributes`](configuration/usage.md#keepattributes) \[*[attribute\_filter](configuration/usage.md#filters)*\] | Preserve the given optional attributes; typically `Exceptions`, `InnerClasses`, `Signature`, `Deprecated`, `SourceFile`, `SourceDir`, `LineNumberTable`, `LocalVariableTable`, `LocalVariableTypeTable`, `Synthetic`, `EnclosingMethod`, and `*Annotation*`.
|
||||
| [`-keepparameternames`](configuration/usage.md#keepparameternames) | Keep the parameter names and types of methods that are kept.
|
||||
| [`-renamesourcefileattribute`](configuration/usage.md#renamesourcefileattribute) \[*string*\] | Put the given constant string in the `SourceFile` attributes.
|
||||
| [`-adaptclassstrings`](configuration/usage.md#adaptclassstrings) \[[*class\_filter*](configuration/usage.md#filters)\] | Adapt string constants in the specified classes, based on the obfuscated names of any corresponding classes.
|
||||
| [`-keepkotlinmetadata`](configuration/usage.md#keepkotlinmetadata) ** deprecated ** | Keep and adapt Kotlin metadata.
|
||||
| [`-adaptresourcefilecontents`](configuration/usage.md#adaptresourcefilecontents) \[[*file\_filter*](configuration/usage.md#filefilters)\] | Update the contents of the specified resource files, based on the obfuscated names of the processed classes.
|
||||
| [`-dontpreverify`](configuration/usage.md#dontpreverify) | Don't preverify the processed class files.
|
||||
| [`-microedition`](configuration/usage.md#microedition) | Target the processed class files at Java Micro Edition.
|
||||
| [`-android`](configuration/usage.md#android) | Target the processed class files at Android.
|
||||
| [`-verbose`](configuration/usage.md#verbose) | Write out some more information during processing.
|
||||
| [`-dontnote`](configuration/usage.md#dontnote) \[[*class\_filter*](configuration/usage.md#filters)\] | Don't print notes about potential mistakes or omissions in the configuration.
|
||||
| [`-dontwarn`](configuration/usage.md#dontwarn) \[[*class\_filter*](configuration/usage.md#filters)\] | Don't warn about unresolved references at all.
|
||||
| [`-ignorewarnings`](configuration/usage.md#ignorewarnings) | Print warnings about unresolved references, but continue processing anyhow.
|
||||
| [`-printconfiguration`](configuration/usage.md#printconfiguration) \[[*filename*](configuration/usage.md#filename)\] | Write out the entire configuration, in traditional ProGuard style, to the standard output or to the given file.
|
||||
| [`-dump`](configuration/usage.md#dump) \[[*filename*](configuration/usage.md#filename)\] | Write out the internal structure of the processed class files, to the standard output or to the given file.
|
||||
| [`-addconfigurationdebugging`](configuration/usage.md#addconfigurationdebugging) | Instrument the processed code with debugging statements that print out suggestions for missing ProGuard configuration.
|
||||
| [`-optimizeaggressively`](configuration/usage.md#optimizeaggressively) | Enables more aggressive assumptions during optimization
|
||||
|
||||
Notes:
|
||||
|
||||
- *class\_path* is a list of jars, apks, aabs, aars, wars, ears, jmods, 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 {: #keepoverview}
|
||||
|
||||
| Keep | From being removed or renamed | From being renamed
|
||||
|-----------------------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------
|
||||
| Classes and class members | [`-keep`](configuration/usage.md#keep) | [`-keepnames`](configuration/usage.md#keepnames)
|
||||
| Class members only | [`-keepclassmembers`](configuration/usage.md#keepclassmembers) | [`-keepclassmembernames`](configuration/usage.md#keepclassmembernames)
|
||||
| Classes and class members, if class members present | [`-keepclasseswithmembers`](configuration/usage.md#keepclasseswithmembers) | [`-keepclasseswithmembernames`](configuration/usage.md#keepclasseswithmembernames)
|
||||
|
||||
The [**ProGuard Playground**](https://playground.proguard.com) is a useful tool to help you further tweak the keep rules.
|
||||
|
||||
<iframe frameborder="0" width="100%" height="200px" style="border-radius: 0.25rem; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);" src="https://playground.proguard.com/p/FT5qr8?embed"></iframe>
|
||||
|
||||
## Keep Option Modifiers {: #keepoptionmodifiers}
|
||||
|
||||
| Modifier | Meaning
|
||||
|-----------------------------------------------------------------|---------------------------------------------------------------------------
|
||||
| [`includedescriptorclasses`](configuration/usage.md#includedescriptorclasses) | Also keep any classes in the descriptors of specified fields and methods.
|
||||
| [`includecode`](configuration/usage.md#includecode) | Also keep the code of the specified methods unchanged.
|
||||
| [`allowshrinking`](configuration/usage.md#allowshrinking) | Allow the specified entry points to be removed in the shrinking step.
|
||||
| [`allowoptimization`](configuration/usage.md#allowoptimization) | Allow the specified entry points to be modified in the optimization step.
|
||||
| [`allowobfuscation`](configuration/usage.md#allowobfuscation) | Allow the specified entry points to be renamed in the obfuscation step.
|
||||
|
||||
## Class Specifications {: #classspecification}
|
||||
|
||||
[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname
|
||||
[extends|implements [@annotationtype] classname]
|
||||
[{
|
||||
[@annotationtype]
|
||||
[[!]public|private|protected|static|volatile|transient ...]
|
||||
<fields> | (fieldtype fieldname [= values]);
|
||||
|
||||
[@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, '`...`' for any number of arguments, and
|
||||
'`<n>`' for the *n*'th matched wildcard in the same option.
|
||||
- *fieldname* and *methodname* can contain wildcards as well: '`?`'
|
||||
for a single character and '`*`' for any number of characters.
|
File diff suppressed because it is too large
Load Diff
@ -1,454 +0,0 @@
|
||||
**ProGuard** can be run as a task in the Java-based build tool Ant
|
||||
(version 1.8 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-ant.jar" />
|
||||
|
||||
Please make sure the class path is set correctly for your system.
|
||||
|
||||
There are three ways to configure the ProGuard task:
|
||||
|
||||
1. using an external configuration file,
|
||||
2. using embedded ProGuard configuration options, or
|
||||
3. using the equivalent XML configuration tags.
|
||||
|
||||
These three ways can be combined, depending on practical circumstances
|
||||
and personal preference.
|
||||
|
||||
## 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 the
|
||||
[**`configuration`**](#configuration_attribute) attribute of your `proguard`
|
||||
task. Your ant build file will then look like this:
|
||||
```xml
|
||||
<taskdef resource="proguard/ant/task.properties"
|
||||
classpath="/usr/local/java/proguard/lib/proguard-ant.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 the **`proguard`**
|
||||
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-ant.jar" />
|
||||
<proguard>
|
||||
-injars in.jar
|
||||
-outjars out.jar
|
||||
-libraryjars ${java.home}/lib/rt.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](../configuration/usage.md) section. You can find some sample
|
||||
configuration files in the **`examples/ant`** directory of the ProGuard
|
||||
distribution.
|
||||
|
||||
### Task Attributes and Nested Elements {: #attributes}
|
||||
|
||||
The **`<proguard>`** task and the `<proguardconfiguration>` task can have
|
||||
the following attributes (only for **`<proguard>`**) and nested elements:
|
||||
|
||||
`configuration`{: #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`**](#configuration_element) *element*.
|
||||
|
||||
[**`skipnonpubliclibraryclasses`**](../configuration/usage.md#skipnonpubliclibraryclasses) = "*boolean*" (default = false)
|
||||
: Ignore non-public library classes.
|
||||
|
||||
[**`skipnonpubliclibraryclassmembers`**](../configuration/usage.md#dontskipnonpubliclibraryclassmembers) = "*boolean*" (default = true)
|
||||
: Ignore package visible library class members.
|
||||
|
||||
[**`target`**](../configuration/usage.md#target) = "*version*" (default = none)
|
||||
: Set the given version number in the processed classes.
|
||||
|
||||
[**`forceprocessing`**](../configuration/usage.md#forceprocessing) = "*boolean*" (default = false)
|
||||
: Process the input, even if the output seems up to date.
|
||||
|
||||
[**`printseeds`**](../configuration/usage.md#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`**](../configuration/usage.md#dontshrink) = "*boolean*" (default = true)
|
||||
: Shrink the input class files.
|
||||
|
||||
[**`printusage`**](../configuration/usage.md#printusage) = "*boolean or filename*" (default = false)
|
||||
: List dead code of the input class files, to the standard output or to the
|
||||
given file.
|
||||
|
||||
[**`optimize`**](../configuration/usage.md#dontoptimize) = "*boolean*" (default = true)
|
||||
: Optimize the input class files.
|
||||
|
||||
[**`optimizationpasses`**](../configuration/usage.md#optimizationpasses) = "*n*" (default = 1)
|
||||
: The number of optimization passes to be performed.
|
||||
|
||||
[**`allowaccessmodification`**](../configuration/usage.md#allowaccessmodification) = "*boolean*" (default = false)
|
||||
: Allow the access modifiers of classes and class members to be modified,
|
||||
while optimizing.
|
||||
|
||||
[**`mergeinterfacesaggressively`**](../configuration/usage.md#mergeinterfacesaggressively) = "*boolean*" (default = false)
|
||||
: Allow any interfaces to be merged, while optimizing.
|
||||
|
||||
[**`obfuscate`**](../configuration/usage.md#dontobfuscate) = "*boolean*" (default = true)
|
||||
: Obfuscate the input class files.
|
||||
|
||||
[**`printmapping`**](../configuration/usage.md#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`**](../configuration/usage.md#applymapping) = "*filename*" (default = none)
|
||||
: Reuse the given mapping, for incremental obfuscation.
|
||||
|
||||
[**`obfuscationdictionary`**](../configuration/usage.md#obfuscationdictionary) = "*filename*" (default = none)
|
||||
: Use the words in the given text file as obfuscated field names and method
|
||||
names.
|
||||
|
||||
[**`classobfuscationdictionary`**](../configuration/usage.md#classobfuscationdictionary) = "*filename*" (default = none)
|
||||
: Use the words in the given text file as obfuscated class names.
|
||||
|
||||
[**`packageobfuscationdictionary`**](../configuration/usage.md#packageobfuscationdictionary) = "*filename*" (default = none)
|
||||
: Use the words in the given text file as obfuscated package names.
|
||||
|
||||
[**`overloadaggressively`**](../configuration/usage.md#overloadaggressively) = "*boolean*" (default = false)
|
||||
: Apply aggressive overloading while obfuscating.
|
||||
|
||||
[**`useuniqueclassmembernames`**](../configuration/usage.md#useuniqueclassmembernames) = "*boolean*" (default = false)
|
||||
: Ensure uniform obfuscated class member names for subsequent incremental
|
||||
obfuscation.
|
||||
|
||||
[**`usemixedcaseclassnames`**](../configuration/usage.md#dontusemixedcaseclassnames) = "*boolean*" (default = true)
|
||||
: Generate mixed-case class names while obfuscating.
|
||||
|
||||
[**`flattenpackagehierarchy`**](../configuration/usage.md#flattenpackagehierarchy) = "*package\_name*" (default = none)
|
||||
: Repackage all packages that are renamed into the single given parent
|
||||
package.
|
||||
|
||||
[**`repackageclasses`**](../configuration/usage.md#repackageclasses) = "*package\_name*" (default = none)
|
||||
: Repackage all class files that are renamed into the single given package.
|
||||
|
||||
[**`keepparameternames`**](../configuration/usage.md#keepparameternames) = "*boolean*" (default = false)
|
||||
: Keep the parameter names and types of methods that are kept.
|
||||
|
||||
[**`renamesourcefileattribute`**](../configuration/usage.md#renamesourcefileattribute) = "*string*" (default = none)
|
||||
: Put the given constant string in the **`SourceFile`** attributes.
|
||||
|
||||
[**`preverify`**](../configuration/usage.md#dontpreverify) = "*boolean*" (default = true)
|
||||
: Preverify the processed class files if they are targeted at Java Micro
|
||||
Edition or at Java 6 or higher.
|
||||
|
||||
[**`microedition`**](../configuration/usage.md#microedition) = "*boolean*" (default = false)
|
||||
: Target the processed class files at Java Micro Edition.
|
||||
|
||||
[**`android`**](../configuration/usage.md#android) = "*boolean*" (default = false)
|
||||
: Target the processed class files at Android.
|
||||
|
||||
[**`verbose`**](../configuration/usage.md#verbose) = "*boolean*" (default = false)
|
||||
: Write out some more information during processing.
|
||||
|
||||
[**`note`**](../configuration/usage.md#dontnote) = "*boolean*" (default = true)
|
||||
: Print notes about potential mistakes or omissions in the configuration.
|
||||
Use the nested element [dontnote](#dontnote) for more fine-grained control.
|
||||
|
||||
[**`warn`**](../configuration/usage.md#dontwarn) = "*boolean*" (default = true)
|
||||
: Print warnings about unresolved references. Use the nested element
|
||||
[dontwarn](#dontwarn) for more fine-grained control. *Only use this option
|
||||
if you know what you're doing!*
|
||||
|
||||
[**`ignorewarnings`**](../configuration/usage.md#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`**](../configuration/usage.md#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`**](../configuration/usage.md#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.
|
||||
|
||||
[**`addconfigurationdebugging`**](../configuration/usage.md#addconfigurationdebugging) = "*boolean*" (default = false)
|
||||
: Adds debugging information to the code, to print out ProGuard
|
||||
configuration suggestions at runtime. *Do not use this option in release
|
||||
versions.*
|
||||
|
||||
[**`<injar`**](../configuration/usage.md#injars) [*class\_path*](#classpath) `/>`
|
||||
: Specifies the program jars (or apks, aabs, aars, wars, ears, jmods, zips, or
|
||||
directories).
|
||||
|
||||
[**`<outjar`**](../configuration/usage.md#outjars) [*class\_path*](#classpath) `/>`
|
||||
: Specifies the names of the output jars (or apks, aabs, aars, wars, ears,
|
||||
jmods, zips, or directories).
|
||||
|
||||
[**`<libraryjar`**](../configuration/usage.md#libraryjars) [*class\_path*](#classpath) `/>`
|
||||
: Specifies the library jars (or apks, aabs, aars, wars, ears, jmods, zips, or
|
||||
directories).
|
||||
|
||||
[**`<keepdirectory name = `**](../configuration/usage.md#keepdirectories)"*directory\_name*" `/>`<br/>[`<keepdirectories filter = `](../configuration/usage.md#keepdirectories)"[*directory\_filter*](../configuration/usage.md#filefilters)" `/>`
|
||||
: Keep the specified directories in the output jars (or apks, aabs, aars, wars,
|
||||
ears, jmods, zips, or directories).
|
||||
|
||||
[**`<keep`**](../configuration/usage.md#keep) [*modifiers*](#keepmodifier) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</keep>`
|
||||
: Preserve the specified classes *and* class members.
|
||||
|
||||
[**`<keepclassmembers`**](../configuration/usage.md#keepclassmembers) [*modifiers*](#keepmodifier) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</keepclassmembers>`
|
||||
: Preserve the specified class members, if their classes are preserved as
|
||||
well.
|
||||
|
||||
[**`<keepclasseswithmembers`**](../configuration/usage.md#keepclasseswithmembers) [*modifiers*](#keepmodifier) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</keepclasseswithmembers>`
|
||||
: Preserve the specified classes *and* class members, if all of the
|
||||
specified class members are present.
|
||||
|
||||
[**`<keepnames`**](../configuration/usage.md#keepnames) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</keepnames>`
|
||||
: Preserve the names of the specified classes *and* class members (if they
|
||||
aren't removed in the shrinking step).
|
||||
|
||||
[**`<keepclassmembernames`**](../configuration/usage.md#keepclassmembernames) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</keepclassmembernames>`
|
||||
: Preserve the names of the specified class members (if they aren't removed
|
||||
in the shrinking step).
|
||||
|
||||
[**`<keepclasseswithmembernames`**](../configuration/usage.md#keepclasseswithmembernames) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</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`**](../configuration/usage.md#whyareyoukeeping) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</whyareyoukeeping>`
|
||||
: Print details on why the given classes and class members are being kept in
|
||||
the shrinking step.
|
||||
|
||||
[**`<assumenosideeffects`**](../configuration/usage.md#assumenosideeffects) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</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!*
|
||||
|
||||
[**`<assumenoexternalsideeffects`**](../configuration/usage.md#assumenoexternalsideeffects) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</assumenoexternalsideeffects>`
|
||||
: Assume that the specified methods don't have any external side effects,
|
||||
while optimizing. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`<assumenoescapingparameters`**](../configuration/usage.md#assumenoescapingparameters) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</assumenoescapingparameters>`
|
||||
: Assume that the specified methods don't let any reference parameters
|
||||
escape to the heap, while optimizing. *Only use this option if you know what
|
||||
you're doing!*
|
||||
|
||||
[**`<assumenoexternalreturnvalues`**](../configuration/usage.md#assumenoexternalreturnvalues) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</assumenoexternalreturnvalues>`
|
||||
: Assume that the specified methods don't return any external reference
|
||||
values, while optimizing. *Only use this option if you know what you're
|
||||
doing!*
|
||||
|
||||
[**`<assumevalues`**](../configuration/usage.md#assumevalues) [*class\_specification*](#classspecification) `>` [*class\_member\_specifications*](#classmemberspecification) `</assumevalues>`
|
||||
: Assume fixed values or ranges of values for primitive fields and methods,
|
||||
while optimizing. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`<optimization name = `**](../configuration/usage.md#optimizations)"[*optimization\_name*](../configuration/optimizations.md)" `/>`<br/>[`<optimizations filter = `](../configuration/usage.md#optimizations)""[*optimization\_filter*](../configuration/optimizations.md)" `/>`
|
||||
: Perform only the specified optimizations.
|
||||
|
||||
[**`<keeppackagename name = `**](../configuration/usage.md#keeppackagenames)"*package\_name*" `/>`<br/>[`<keeppackagenames filter = `](../configuration/usage.md#keeppackagenames)"[*package\_filter*](../configuration/usage.md#filters)" `/>`
|
||||
: Keep the specified package names from being obfuscated. If no name is
|
||||
given, all package names are preserved.
|
||||
|
||||
[**`<keepattribute name = `**](../configuration/usage.md#keepattributes)"*attribute\_name*" `/>`<br/>[`<keepattributes filter = `](../configuration/usage.md#keepattributes)"[*attribute\_filter*](../configuration/usage.md#filters)" `/>`
|
||||
: Preserve the specified optional Java bytecode attributes, with optional
|
||||
wildcards. If no name is given, all attributes are preserved.
|
||||
|
||||
[**`<adaptclassstrings filter = `**](../configuration/usage.md#adaptclassstrings)"[*class\_filter*](../configuration/usage.md#filters)" `/>`
|
||||
: Adapt string constants in the specified classes, based on the obfuscated
|
||||
names of any corresponding classes.
|
||||
|
||||
[**`<adaptresourcefilenames filter = `**](../configuration/usage.md#adaptresourcefilenames)"[*file\_filter*](../configuration/usage.md#filefilters)" `/>`
|
||||
: Rename the specified resource files, based on the obfuscated names of the
|
||||
corresponding class files.
|
||||
|
||||
[**`<adaptresourcefilecontents filter = `**](../configuration/usage.md#adaptresourcefilecontents)"[*file\_filter*](../configuration/usage.md#filefilters)" `/>`
|
||||
: Update the contents of the specified resource files, based on the
|
||||
obfuscated names of the processed classes.
|
||||
|
||||
[**`<dontnote filter = `**](../configuration/usage.md#dontnote)"[*class\_filter*](../configuration/usage.md#filters)" `/>`
|
||||
: Don't print notes about classes matching the specified class name filter.
|
||||
|
||||
[**`<dontwarn filter = `**](../configuration/usage.md#dontwarn)"[*class\_filter*](../configuration/usage.md#filters)" `/>`
|
||||
: 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 = `{: #configuration_element } "*ref\_id*" `/>`<br/>`<configuration file = `"*name*" `/>`
|
||||
: The first form includes the XML-style configuration specified in a
|
||||
**`<proguardconfiguration>`** task (or `<proguard>` task) with attribute
|
||||
**`id`** = "*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 {: #classpath}
|
||||
|
||||
The jar elements are **`path`** elements, so they can have any of the
|
||||
standard **`path`** attributes and nested elements. The most common
|
||||
attributes are:
|
||||
|
||||
`path` = "*path*"
|
||||
: The names of the jars (or apks, aabs, aars, wars, ears, jmods, zips, or
|
||||
directories), separated by the path separator.
|
||||
|
||||
`location` = "*name*" (or `file` = "*name*", or `dir` = "*name*", or `name` = "*name*")
|
||||
: Alternatively, the name of a single jar (or apk, aab, aar, war, ear, jmod,
|
||||
zip, or directory).
|
||||
|
||||
`refid` = "*ref\_id*"
|
||||
: Alternatively, a reference to the path or file set with the attribute
|
||||
**`id`** = "*ref\_id*".
|
||||
|
||||
In addition, the jar elements can have ProGuard-style filter attributes:
|
||||
|
||||
`filter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all class file names and resource file names that
|
||||
are encountered.
|
||||
|
||||
`apkfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all apk names that are encountered.
|
||||
|
||||
`aabfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all aab names that are encountered.
|
||||
|
||||
`jarfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all jar names that are encountered.
|
||||
|
||||
`aarfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all aar names that are encountered.
|
||||
|
||||
`warfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all war names that are encountered.
|
||||
|
||||
`earfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all ear names that are encountered.
|
||||
|
||||
`jmodfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all jmod names that are encountered.
|
||||
|
||||
`zipfilter` = "[*file\_filter*](../configuration/usage.md#filefilters)"
|
||||
: An optional filter for all zip names that are encountered.
|
||||
|
||||
## Keep Modifier Attributes {: #keepmodifier}
|
||||
|
||||
The keep tags can have the following *modifier* attributes:
|
||||
|
||||
[**`includedescriptorclasses`**](../configuration/usage.md#includedescriptorclasses) = "*boolean*" (default = false)
|
||||
: Specifies whether the classes of the fields and methods specified in the
|
||||
keep tag must be kept as well.
|
||||
|
||||
[**`allowshrinking`**](../configuration/usage.md#allowshrinking) = "*boolean*" (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
shrunk.
|
||||
|
||||
[**`allowoptimization`**](../configuration/usage.md#allowoptimization) = "*boolean*" (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
optimized.
|
||||
|
||||
[**`allowobfuscation`**](../configuration/usage.md#allowobfuscation) = "*boolean*" (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
obfuscated.
|
||||
|
||||
## Class Specification Attributes and Nested Elements {: #classspecification}
|
||||
|
||||
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*](#classmemberspecification) `/>`
|
||||
: Specifies a field.
|
||||
|
||||
`<method` [*class\_member\_specification*](#classmemberspecification) `/>`
|
||||
: Specifies a method.
|
||||
|
||||
`<constructor` [*class\_member\_specification*](#classmemberspecification) `/>`
|
||||
: Specifies a constructor.
|
||||
|
||||
## Class Member Specification Attributes {: #classmemberspecification}
|
||||
|
||||
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.
|
||||
|
||||
`values` = "*values*"
|
||||
: The optional fixed value or range of values for a primitive field
|
||||
or method.
|
@ -1,470 +0,0 @@
|
||||
**ProGuard** can be run as a task in the Java-based build tool Gradle
|
||||
(version 2.1 or higher).
|
||||
|
||||
!!! android "Android projects"
|
||||
If you have an Android project, you can find instructions [here](gradleplugin.md).
|
||||
|
||||
|
||||
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 your **`build.gradle`** file:
|
||||
```Groovy
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.guardsquare:proguard-gradle:7.1.0'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please make sure the class path is set correctly for your system.
|
||||
|
||||
You can then define a task:
|
||||
```Groovy
|
||||
task myProguardTask(type: proguard.gradle.ProGuardTask) {
|
||||
.....
|
||||
}
|
||||
```
|
||||
|
||||
The embedded configuration is much like a standard ProGuard
|
||||
configuration. Notable similarities and differences:
|
||||
|
||||
- Like in ProGuard 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](#anttask).
|
||||
|
||||
## Settings {: #proguard}
|
||||
|
||||
The ProGuard task supports the following settings in its closure:
|
||||
|
||||
`configuration` [*files*](#file)
|
||||
: Read and merge options from the given ProGuard configuration files.
|
||||
The files are resolved and parsed lazily, during the execution phase.
|
||||
|
||||
[**`injars`**](../configuration/usage.md#injars) [*class\_path*](#classpath)
|
||||
: Specifies the program jars (or apks, aabs, aars, wars, ears, jmods, zips, or
|
||||
directories). The files are resolved and read lazily, during the execution
|
||||
phase.
|
||||
|
||||
[**`outjars`**](../configuration/usage.md#outjars) [*class\_path*](#classpath)
|
||||
: Specifies the names of the output jars (or apks, aabs, aars, wars, ears,
|
||||
jmods, zips, or directories). The files are resolved and written lazily,
|
||||
during the execution phase.
|
||||
|
||||
[**`libraryjars`**](../configuration/usage.md#libraryjars) [*class\_path*](#classpath)
|
||||
: Specifies the names of the output jars (or apks, aabs, aars, wars, ears,
|
||||
jmods, zips, or directories). The files are resolved and written lazily,
|
||||
during the execution phase.
|
||||
|
||||
[**`skipnonpubliclibraryclasses`**](../configuration/usage.md#skipnonpubliclibraryclasses)
|
||||
: Ignore non-public library classes.
|
||||
|
||||
[**`dontskipnonpubliclibraryclassmembers`**](../configuration/usage.md#dontskipnonpubliclibraryclassmembers)
|
||||
: Don't ignore package visible library class members.
|
||||
|
||||
[**`keepdirectories`**](../configuration/usage.md#keepdirectories) \['[*directory\_filter*](../configuration/usage.md#filefilters)'\]
|
||||
: Keep the specified directories in the output jars (or apks, aabs, aars, wars,
|
||||
ears, jmods, zips, or directories).
|
||||
|
||||
[**`target`**](../configuration/usage.md#target) '*version*'
|
||||
: Set the given version number in the processed classes.
|
||||
|
||||
[**`forceprocessing`**](../configuration/usage.md#forceprocessing)
|
||||
: Process the input, even if the output seems up to date.
|
||||
|
||||
[**`keep`**](../configuration/usage.md#keep) \[[*modifier*,...](#keepmodifier)\] [*class\_specification*](#classspecification)
|
||||
: Preserve the specified classes *and* class members.
|
||||
|
||||
[**`keepclassmembers`**](../configuration/usage.md#keepclassmembers) \[[*modifier*,...](#keepmodifier)\] [*class\_specification*](#classspecification)
|
||||
: Preserve the specified class members, if their classes are preserved as
|
||||
well.
|
||||
|
||||
[**`keepclasseswithmembers`**](../configuration/usage.md#keepclasseswithmembers) \[[*modifier*,...](#keepmodifier)\] [*class\_specification*](#classspecification)
|
||||
: Preserve the specified classes *and* class members, if all of the
|
||||
specified class members are present.
|
||||
|
||||
[**`keepnames`**](../configuration/usage.md#keepnames) [*class\_specification*](#classspecification)
|
||||
: Preserve the names of the specified classes *and* class members (if they
|
||||
aren't removed in the shrinking step).
|
||||
|
||||
[**`keepclassmembernames`**](../configuration/usage.md#keepclassmembernames) [*class\_specification*](#classspecification)
|
||||
: Preserve the names of the specified class members (if they aren't removed
|
||||
in the shrinking step).
|
||||
|
||||
[**`keepclasseswithmembernames`**](../configuration/usage.md#keepclasseswithmembernames) [*class\_specification*](#classspecification)
|
||||
: Preserve the names of the specified classes *and* class members, if all of
|
||||
the specified class members are present (after the shrinking step).
|
||||
|
||||
[**`printseeds`**](../configuration/usage.md#printseeds) \[[*file*](#file)\]
|
||||
: List classes and class members matched by the various **`keep`** commands,
|
||||
to the standard output or to the given file.
|
||||
|
||||
[**`dontshrink`**](../configuration/usage.md#dontshrink)
|
||||
: Don't shrink the input class files.
|
||||
|
||||
[**`printusage`**](../configuration/usage.md#printusage) \[[*file*](#file)\]
|
||||
: List dead code of the input class files, to the standard output or to the
|
||||
given file.
|
||||
|
||||
[**`whyareyoukeeping`**](../configuration/usage.md#whyareyoukeeping) [*class\_specification*](#classspecification)
|
||||
: Print details on why the given classes and class members are being kept in
|
||||
the shrinking step.
|
||||
|
||||
[**`dontoptimize`**](../configuration/usage.md#dontoptimize)
|
||||
: Don't optimize the input class files.
|
||||
|
||||
[**`optimizations`**](../configuration/usage.md#optimizations) '[*optimization\_filter*](../configuration/optimizations.md)'
|
||||
: Perform only the specified optimizations.
|
||||
|
||||
[**`optimizationpasses`**](../configuration/usage.md#optimizationpasses) *n*
|
||||
: The number of optimization passes to be performed.
|
||||
|
||||
[**`assumenosideeffects`**](../configuration/usage.md#assumenosideeffects) [*class\_specification*](#classspecification)
|
||||
: Assume that the specified methods don't have any side effects, while
|
||||
optimizing. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`assumenoexternalsideeffects`**](../configuration/usage.md#assumenoexternalsideeffects) [*class\_specification*](#classspecification)
|
||||
: Assume that the specified methods don't have any external side effects,
|
||||
while optimizing. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`assumenoescapingparameters`**](../configuration/usage.md#assumenoescapingparameters) [*class\_specification*](#classspecification)
|
||||
: Assume that the specified methods don't let any reference parameters
|
||||
escape to the heap, while optimizing. *Only use this option if you know what
|
||||
you're doing!*
|
||||
|
||||
[**`assumenoexternalreturnvalues`**](../configuration/usage.md#assumenoexternalreturnvalues) [*class\_specification*](#classspecification)
|
||||
: Assume that the specified methods don't return any external reference
|
||||
values, while optimizing. *Only use this option if you know what you're
|
||||
doing!*
|
||||
|
||||
[**`assumevalues`**](../configuration/usage.md#assumevalues) [*class\_specification*](#classspecification)
|
||||
: Assume fixed values or ranges of values for primitive fields and methods,
|
||||
while optimizing. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`allowaccessmodification`**](../configuration/usage.md#allowaccessmodification)
|
||||
: Allow the access modifiers of classes and class members to be modified,
|
||||
while optimizing.
|
||||
|
||||
[**`mergeinterfacesaggressively`**](../configuration/usage.md#mergeinterfacesaggressively)
|
||||
: Allow any interfaces to be merged, while optimizing.
|
||||
|
||||
[**`dontobfuscate`**](../configuration/usage.md#dontobfuscate)
|
||||
: Don't obfuscate the input class files.
|
||||
|
||||
[**`printmapping`**](../configuration/usage.md#printmapping) \[[*file*](#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`**](../configuration/usage.md#applymapping) [*file*](#file)
|
||||
: Reuse the given mapping, for incremental obfuscation.
|
||||
|
||||
[**`obfuscationdictionary`**](../configuration/usage.md#obfuscationdictionary) [*file*](#file)
|
||||
: Use the words in the given text file as obfuscated field names and method
|
||||
names.
|
||||
|
||||
[**`classobfuscationdictionary`**](../configuration/usage.md#classobfuscationdictionary) [*file*](#file)
|
||||
: Use the words in the given text file as obfuscated class names.
|
||||
|
||||
[**`packageobfuscationdictionary`**](../configuration/usage.md#packageobfuscationdictionary) [*file*](#file)
|
||||
: Use the words in the given text file as obfuscated package names.
|
||||
|
||||
[**`overloadaggressively`**](../configuration/usage.md#overloadaggressively)
|
||||
: Apply aggressive overloading while obfuscating.
|
||||
|
||||
[**`useuniqueclassmembernames`**](../configuration/usage.md#useuniqueclassmembernames)
|
||||
: Ensure uniform obfuscated class member names for subsequent incremental
|
||||
obfuscation.
|
||||
|
||||
[**`dontusemixedcaseclassnames`**](../configuration/usage.md#dontusemixedcaseclassnames)
|
||||
: Don't generate mixed-case class names while obfuscating.
|
||||
|
||||
[**`keeppackagenames`**](../configuration/usage.md#keeppackagenames) \['[*package\_filter*](../configuration/usage.md#filters)'\]
|
||||
: Keep the specified package names from being obfuscated. If no name is
|
||||
given, all package names are preserved.
|
||||
|
||||
[**`flattenpackagehierarchy`**](../configuration/usage.md#flattenpackagehierarchy) '*package\_name*'
|
||||
: Repackage all packages that are renamed into the single given parent
|
||||
package.
|
||||
|
||||
[**`repackageclasses`**](../configuration/usage.md#repackageclasses) \['*package\_name*'\]
|
||||
: Repackage all class files that are renamed into the single given package.
|
||||
|
||||
[**`keepattributes`**](../configuration/usage.md#keepattributes) \['[*attribute\_filter*](../configuration/usage.md#filters)'\]
|
||||
: Preserve the specified optional Java bytecode attributes, with optional
|
||||
wildcards. If no name is given, all attributes are preserved.
|
||||
|
||||
[**`keepparameternames`**](../configuration/usage.md#keepparameternames)
|
||||
: Keep the parameter names and types of methods that are kept.
|
||||
|
||||
[**`renamesourcefileattribute`**](../configuration/usage.md#renamesourcefileattribute) \['*string*'\]
|
||||
: Put the given constant string in the **`SourceFile`** attributes.
|
||||
|
||||
[**`adaptclassstrings`**](../configuration/usage.md#adaptclassstrings) \['[*class\_filter*](../configuration/usage.md#filters)'\]
|
||||
: Adapt string constants in the specified classes, based on the obfuscated
|
||||
names of any corresponding classes.
|
||||
|
||||
[**`adaptresourcefilenames`**](../configuration/usage.md#adaptresourcefilenames) \['[*file\_filter*](../configuration/usage.md#filefilters)'\]
|
||||
: Rename the specified resource files, based on the obfuscated names of the
|
||||
corresponding class files.
|
||||
|
||||
[**`adaptresourcefilecontents`**](../configuration/usage.md#adaptresourcefilecontents) \['[*file\_filter*](../configuration/usage.md#filefilters)'\]
|
||||
: Update the contents of the specified resource files, based on the
|
||||
obfuscated names of the processed classes.
|
||||
|
||||
[**`dontpreverify`**](../configuration/usage.md#dontpreverify)
|
||||
: Don't preverify the processed class files if they are targeted at Java
|
||||
Micro Edition or at Java 6 or higher.
|
||||
|
||||
[**`microedition`**](../configuration/usage.md#microedition)
|
||||
: Target the processed class files at Java Micro Edition.
|
||||
|
||||
[**`android`**](../configuration/usage.md#android)
|
||||
: Target the processed class files at Android.
|
||||
|
||||
[**`verbose`**](../configuration/usage.md#verbose)
|
||||
: Write out some more information during processing.
|
||||
|
||||
[**`dontnote`**](../configuration/usage.md#dontnote) '[*class\_filter*](../configuration/usage.md#filters)'
|
||||
: Don't print notes about classes matching the specified class name filter.
|
||||
|
||||
[**`dontwarn`**](../configuration/usage.md#dontwarn) '[*class\_filter*](../configuration/usage.md#filters)'
|
||||
: Don't print warnings about classes matching the specified class name
|
||||
filter. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`ignorewarnings`**](../configuration/usage.md#ignorewarnings)
|
||||
: Print warnings about unresolved references, but continue processing
|
||||
anyhow. *Only use this option if you know what you're doing!*
|
||||
|
||||
[**`printconfiguration`**](../configuration/usage.md#printconfiguration) \[[*file*](#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`**](../configuration/usage.md#dump) \[[*file*](#file)\]
|
||||
: Write out the internal structure of the processed class files, to the
|
||||
standard output or to the given file.
|
||||
|
||||
[**`addconfigurationdebugging`**](../configuration/usage.md#addconfigurationdebugging)
|
||||
: Adds debugging information to the code, to print out ProGuard
|
||||
configuration suggestions at runtime. *Do not use this option in release
|
||||
versions.*
|
||||
|
||||
## Class Paths {: #classpath}
|
||||
|
||||
Class paths are specified as Gradle file collections, which means they
|
||||
can be specified as simple strings, with **`files(Object)`**, etc.
|
||||
|
||||
In addition, they can have ProGuard filters, specified as
|
||||
comma-separated named arguments after the file:
|
||||
|
||||
`filter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all class file names and resource file names that
|
||||
are encountered.
|
||||
|
||||
`apkfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all apk names that are encountered.
|
||||
|
||||
`jarfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all jar names that are encountered.
|
||||
|
||||
`aarfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all aar names that are encountered.
|
||||
|
||||
`warfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all war names that are encountered.
|
||||
|
||||
`earfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all ear names that are encountered.
|
||||
|
||||
`zipfilter:` '[*file\_filter*](../configuration/usage.md#filefilters)'
|
||||
: An optional filter for all zip names that are encountered.
|
||||
|
||||
## Files {: #file}
|
||||
|
||||
Files are specified as Gradle files, which means they can be specified
|
||||
as simple strings, as File instances, with `file(Object)`, etc.
|
||||
|
||||
In Gradle, file names (any strings really) in double quotes can contain
|
||||
properties or code inside `${...}`. These are automatically expanded.
|
||||
|
||||
For example, `"${System.getProperty('java.home')}/lib/rt.jar"` is
|
||||
expanded to something like `'/usr/local/java/jdk/jre/lib/rt.jar'`.
|
||||
Similarly, `System.getProperty('user.home')` is expanded to the user's
|
||||
home directory, and `System.getProperty('user.dir')` is expanded to the
|
||||
current working directory.
|
||||
|
||||
## Keep Modifiers {: #keepmodifier}
|
||||
|
||||
The keep settings can have the following named arguments that modify
|
||||
their behaviors:
|
||||
|
||||
[**`if:`**](../configuration/usage.md#if) [*class\_specification*](#classspecification)
|
||||
: Specifies classes and class members that must be present to activate the
|
||||
keep option.
|
||||
|
||||
[**`includedescriptorclasses:`**](../configuration/usage.md#includedescriptorclasses) *boolean* (default = false)
|
||||
: Specifies whether the classes of the fields and methods specified in the
|
||||
keep tag must be kept as well.
|
||||
|
||||
[**`allowshrinking:`**](../configuration/usage.md#allowshrinking) *boolean* (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
shrunk.
|
||||
|
||||
[**`allowoptimization:`**](../configuration/usage.md#allowoptimization) *boolean* (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
optimized.
|
||||
|
||||
[**`allowobfuscation:`**](../configuration/usage.md#allowobfuscation) *boolean* (default = false)
|
||||
: Specifies whether the entry points specified in the keep tag may be
|
||||
obfuscated.
|
||||
|
||||
Names arguments are comma-separated, as usual.
|
||||
|
||||
## Class Specifications {: #classspecification}
|
||||
|
||||
A class specification is a template of classes and class members (fields
|
||||
and methods). There are two alternative ways to specify such a template:
|
||||
|
||||
1. As a string containing a ProGuard 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:
|
||||
```Groovy
|
||||
keep 'public class com.example.MyMainClass { \
|
||||
public static void main(java.lang.String[]); \
|
||||
}'
|
||||
```
|
||||
|
||||
2. As a Gradle-style setting: a method call with named arguments and
|
||||
a closure. This is more verbose, but it might be useful for
|
||||
programmatic specifications. For example:
|
||||
```Groovy
|
||||
keep access: 'public',
|
||||
name: 'com.example.MyMainClass', {
|
||||
method access: 'public static',
|
||||
type: 'void',
|
||||
name: 'main',
|
||||
parameters: 'java.lang.String[]'
|
||||
}
|
||||
```
|
||||
|
||||
The [ProGuard class specification](../configuration/usage.md#classspecification)
|
||||
is described on the traditional Usage page.
|
||||
|
||||
A Gradle-style class specification can have the following named
|
||||
arguments:
|
||||
|
||||
`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.
|
||||
|
||||
The named arguments are optional. Without any arguments, there are no
|
||||
constraints, so the settings match all classes.
|
||||
|
||||
## Gradle-style Class Member Specifications {: #classmemberspecification}
|
||||
|
||||
The closure of a Gradle-style class specification can specify class
|
||||
members with these settings:
|
||||
|
||||
`field` *field\_constraints*
|
||||
: Specifies a field.
|
||||
|
||||
`method` *method\_constraints*
|
||||
: Specifies a method.
|
||||
|
||||
`constructor` *constructor\_constraints*
|
||||
: Specifies a constructor.
|
||||
|
||||
A class member setting can have the following named arguments to express
|
||||
constraints:
|
||||
|
||||
`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.
|
||||
|
||||
The named arguments are optional. Without any arguments, there are no
|
||||
constraints, so the settings match all constructors, fields, or methods.
|
||||
|
||||
A class member setting doesn't have a closure.
|
||||
|
||||
## Alternative: imported Ant task {: #anttask}
|
||||
|
||||
Instead of using the Gradle task, you could also integrate the Ant task
|
||||
in your Gradle build file:
|
||||
```proguard
|
||||
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:
|
||||
```proguard
|
||||
task proguard << {
|
||||
ant.proguard(printmapping: 'proguard.map',
|
||||
overloadaggressively: 'on',
|
||||
repackageclasses: '',
|
||||
renamesourcefileattribute: 'SourceFile') {
|
||||
|
||||
injar(file: 'application.jar')
|
||||
injar(file: 'gui.jar', filter: '!META-INF/**')
|
||||
|
||||
.....
|
||||
}
|
||||
}
|
||||
```
|
@ -1,250 +0,0 @@
|
||||
|
||||
This page will guide you through to the basic steps of processing your Android application or library with ProGuard.
|
||||
|
||||
!!! tip "Java / Kotlin desktop or server projects"
|
||||
If you have a Java / Kotlin desktop or server project, you can find instructions [here](gradle.md).
|
||||
|
||||
## ProGuard Gradle Plugin (AGP version 4.x - AGP 7.x)
|
||||
|
||||
You can add the ProGuard plugin to your project by
|
||||
including the following in your root level `build.gradle(.kts)` file:
|
||||
|
||||
=== "Groovy"
|
||||
```Groovy
|
||||
buildscript {
|
||||
repositories {
|
||||
google() // For the Android Gradle plugin.
|
||||
mavenCentral() // For the ProGuard Gradle Plugin and anything else.
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:x.y.z' // The Android Gradle plugin.
|
||||
classpath 'com.guardsquare:proguard-gradle:7.1.0' // The ProGuard Gradle plugin.
|
||||
}
|
||||
}
|
||||
```
|
||||
=== "Kotlin"
|
||||
```kotlin
|
||||
buildscript {
|
||||
repositories {
|
||||
google() // For the Android Gradle plugin.
|
||||
mavenCentral() // For the ProGuard Gradle Plugin and anything else.
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:x.y.z") // The Android Gradle plugin.
|
||||
classpath("com.guardsquare:proguard-gradle:7.1.0") // The ProGuard Gradle plugin.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To actually apply the plugin to your project,
|
||||
just add the line to your module level `build.gradle(.kts)` file after applying the Android Gradle plugin as shown below.
|
||||
|
||||
=== "Groovy"
|
||||
```Groovy
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'com.guardsquare.proguard'
|
||||
```
|
||||
=== "Kotlin"
|
||||
```kotlin
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("proguard")
|
||||
}
|
||||
```
|
||||
|
||||
ProGuard expects unobfuscated class files as input. Therefore, other obfuscators such as R8 have to be disabled.
|
||||
|
||||
=== "Groovy"
|
||||
```Groovy
|
||||
android {
|
||||
...
|
||||
buildTypes {
|
||||
release {
|
||||
// Deactivate R8.
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
=== "Kotlin"
|
||||
```kotlin
|
||||
android {
|
||||
...
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
// Deactivate R8.
|
||||
isMinifyEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
ProGuard can be executed automatically whenever you build any of the configured variants.
|
||||
You can configure a variant using the `proguard` block in your module level `build.gradle(.kts)` files.
|
||||
This is a top-level block and should be placed outside the `android` block.
|
||||
|
||||
For example, in the snippet below, ProGuard is configured to only process the release variant of the application,
|
||||
using a configuration provided by the user (`proguard-project.txt`) and a [default configuration](#default-configurations) (`proguard-android-optimize.txt`).
|
||||
|
||||
=== "Groovy"
|
||||
```Groovy
|
||||
android {
|
||||
...
|
||||
}
|
||||
|
||||
proguard {
|
||||
configurations {
|
||||
release {
|
||||
defaultConfiguration 'proguard-android-optimize.txt'
|
||||
configuration 'proguard-project.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
=== "Kotlin"
|
||||
```kotlin
|
||||
android {
|
||||
...
|
||||
}
|
||||
|
||||
proguard {
|
||||
configurations {
|
||||
register("release") {
|
||||
defaultConfiguration("proguard-android-optimize.txt")
|
||||
configuration("proguard-project.txt")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can then build your application as usual:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```sh
|
||||
./gradlew assembleRelease
|
||||
```
|
||||
=== "Windows"
|
||||
```
|
||||
gradlew assembleRelease
|
||||
```
|
||||
|
||||
### Default configurations
|
||||
|
||||
There are three default configurations available:
|
||||
|
||||
| Default configuration | Description |
|
||||
|-----------------------|-------------|
|
||||
| `proguard-android.txt` | ProGuard will obfuscate and shrink your application |
|
||||
| `proguard-android-optimize.txt` | ProGuard will obfuscate, shrink and optimize your application |
|
||||
| `proguard-android-debug.txt` | ProGuard will process the application without any obfuscation,<br>optimization or shrinking |
|
||||
|
||||
### Consumer rules
|
||||
|
||||
ProGuard will apply the consumer rules provided by library dependencies. If you need to exclude these rules,
|
||||
you can use the `consumerRuleFilter`.
|
||||
|
||||
#### consumerRuleFilter
|
||||
|
||||
The `consumerRuleFilter` option allows you to specify a list of maven group and
|
||||
module name pairs to filter out the ProGuard consumer rules of the dependencies
|
||||
that match the specified group and module pairs.
|
||||
|
||||
A group and module name pair is very similar to the maven coordinates you write
|
||||
when specifying the dependencies in the `dependencies` block, but without the
|
||||
version part.
|
||||
|
||||
=== "Groovy"
|
||||
```Groovy
|
||||
proguard {
|
||||
configurations {
|
||||
release {
|
||||
consumerRuleFilter 'groupName:moduleName', 'anotherGroupName:anotherModuleName'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
=== "Kotlin"
|
||||
```Kotlin
|
||||
proguard {
|
||||
configurations {
|
||||
register("release") {
|
||||
consumerRuleFilter("groupName:moduleName", "anotherGroupName:anotherModuleName")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
The example [`android-plugin`](https://github.com/Guardsquare/proguard/tree/master/examples/android-plugin)
|
||||
has a small working Android project using the ProGuard Gradle Plugin.
|
||||
|
||||
## AGP Integrated ProGuard (AGP version <7)
|
||||
|
||||
ProGuard is integrated with older versions of the Android Gradle plugin.
|
||||
If you have an Android Gradle project that uses such an AGP version,
|
||||
you can enable ProGuard instead of the default `R8` obfuscator as follows:
|
||||
|
||||
1. Disable R8 in your `gradle.properties`:
|
||||
```ini
|
||||
android.enableR8=false
|
||||
android.enableR8.libraries=false
|
||||
```
|
||||
|
||||
2. Override the default version of ProGuard with the most recent one in your
|
||||
main `build.gradle`:
|
||||
```Groovy
|
||||
buildscript {
|
||||
...
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
dependencySubstitution {
|
||||
substitute module('net.sf.proguard:proguard-gradle') with module('com.guardsquare:proguard-gradle:7.1.0')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Enable minification as usual in your `build.gradle`:
|
||||
```Groovy
|
||||
android {
|
||||
...
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
|
||||
proguardFile 'proguard-project.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There are two default configurations available when using the integrated ProGuard:
|
||||
|
||||
| Default configuration | Description |
|
||||
|-----------------------|-------------|
|
||||
| `proguard-android.txt` | ProGuard will obfuscate and shrink your application |
|
||||
| `proguard-android-optimize.txt` | ProGuard will obfuscate, shrink and optimize your application |
|
||||
|
||||
4. Add any necessary configuration to your `proguard-project.txt`.
|
||||
|
||||
You can then build your application as usual:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```sh
|
||||
./gradlew assembleRelease
|
||||
```
|
||||
=== "Windows"
|
||||
```
|
||||
gradlew assembleRelease
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
The example [`android-agp3-agp4`](https://github.com/Guardsquare/proguard/tree/master/examples/android-agp3-agp4)
|
||||
has a small working Android project for AGP < 7.
|
||||
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
To run ProGuard, just type:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
bin/proguard.sh <options...>
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```
|
||||
bin\proguard <options...>
|
||||
```
|
||||
|
||||
Typically, you'll put most options in a configuration file (say,
|
||||
`myconfig.pro`), and just call:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
bin/proguard.sh @myconfig.pro
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```bash
|
||||
bin\proguard @myconfig.pro
|
||||
```
|
||||
|
||||
You can combine command line options and options from configuration
|
||||
files. For instance:
|
||||
|
||||
=== "Linux/macOS"
|
||||
```bash
|
||||
bin/proguard.sh @myconfig.pro -verbose
|
||||
```
|
||||
|
||||
=== "Windows"
|
||||
```
|
||||
bin\proguard @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.
|
||||
|
||||
All available options are described in the [Configuration section](../configuration/usage.md).
|
@ -1,8 +0,0 @@
|
||||
# AppSweep
|
||||
|
||||
[AppSweep](https://appsweep.guardsquare.com/) is a free online app security testing tool that allows you to find and fix security
|
||||
issues in your Android app's code and dependencies.
|
||||
|
||||
<center>
|
||||

|
||||
</center>
|
@ -1,7 +0,0 @@
|
||||
# ProGuard Playground
|
||||
|
||||
[ProGuard Playground](https://playground.proguard.com/) is an online rule visualizer tool compatible with ProGuard, R8 and DexGuard
|
||||
keep rules. It allows you to write keep rules and in real-time see which entities in your app
|
||||
will be matched by those rules.
|
||||
|
||||
<iframe frameborder="0" width="100%" height="400px" style="border-radius: 0.25rem; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);" src="https://playground.proguard.com/p/FT5qr8?embed"></iframe>
|
@ -1,382 +0,0 @@
|
||||
# ReTrace
|
||||
|
||||
**ReTrace** is a companion tool for ProGuard and DexGuard 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.
|
||||
|
||||
<img src="PG_ReTrace.png" alt="ReTrace deobfuscation workflow" style="display: block; margin-left: auto; margin-right: auto;" />
|
||||
|
||||
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 an obfuscator (like ProGuard, DexGuard or R8) can write out while obfuscating. The mapping
|
||||
file links the original class names and class member names to their
|
||||
obfuscated names.
|
||||
|
||||
## Usage {: #usage }
|
||||
|
||||
You can find the ReTrace jar in the `lib` directory of the ProGuard
|
||||
distribution. To run ReTrace, just type:
|
||||
|
||||
`java -jar retrace.jar `\[*options...*\] *mapping\_file*
|
||||
\[*stacktrace\_file*\]
|
||||
|
||||
Alternatively, the `bin` directory contains some short Linux and Windows
|
||||
scripts containing this command. These are the arguments:
|
||||
|
||||
*mapping\_file*
|
||||
: Specifies the name of the mapping file.
|
||||
|
||||
*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. The
|
||||
stack trace must be encoded with UTF-8 encoding. Blank lines and
|
||||
unrecognized lines are ignored.
|
||||
|
||||
The following options are supported:
|
||||
|
||||
`-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. A relatively
|
||||
simple expression like this works for basic stack trace formats:
|
||||
|
||||
(?:.*? at %c\.%m\(%s(?::%l)?\))|(?:(?:.*?[:"] +)?%c(?::.*)?)
|
||||
|
||||
It for instance matches the following lines:
|
||||
|
||||
Exception in thread "main" myapplication.MyException: Some message
|
||||
at com.example.MyClass.myMethod(MyClass.java:123)
|
||||
|
||||
The regular expression is a Java regular expression (cfr. the
|
||||
documentation of `java.util.regex.Pattern`), with a few additional
|
||||
wildcards:
|
||||
|
||||
| Wildcard | Description | Example
|
||||
|----------|--------------------------------------------|-------------------------------------------
|
||||
| `%c` | matches a class name | `com.example.MyClass`
|
||||
| `%C` | matches a class name with slashes | `com/example/MyClass`
|
||||
| `%t` | matches a field type or method return type | `com.example.MyClass[]`
|
||||
| `%f` | matches a field name | `myField`
|
||||
| `%m` | matches a method name | `myMethod`
|
||||
| `%a` | matches a list of method arguments | `boolean,int`
|
||||
| `%s` | matches a source file name | `MyClass.java`
|
||||
| `%l` | matches a line number inside a method | `123`
|
||||
|
||||
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: `(?:`...`)`
|
||||
|
||||
You can print out the default regular expression by running ReTrace without
|
||||
arguments. It also matches more complex stack traces.
|
||||
|
||||
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:
|
||||
|
||||
- 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.
|
||||
|
||||
Source file names are currently restored based on the names of the
|
||||
outer-most classes. If you prefer to keep the obfuscated name, you can
|
||||
replace `%s` in the default regular expression by `.*`
|
||||
|
||||
Unobfuscated elements and obfuscated elements for which no mapping is
|
||||
available will be left unchanged.
|
||||
|
||||
|
||||
## Examples {: #examples }
|
||||
|
||||
### Restoring a stack trace with line numbers {: #with}
|
||||
|
||||
Assume for instance an application has been obfuscated using the
|
||||
following extra options:
|
||||
|
||||
-printmapping mapping.txt
|
||||
|
||||
-renamesourcefileattribute MyApplication
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
Now assume the processed application throws an exception:
|
||||
|
||||
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
|
||||
at proguard.y.a(MyApplication:188)
|
||||
at proguard.y.a(MyApplication:158)
|
||||
at proguard.y.a(MyApplication:136)
|
||||
at proguard.y.a(MyApplication:66)
|
||||
at proguard.ProGuard.c(MyApplication:218)
|
||||
at proguard.ProGuard.a(MyApplication:82)
|
||||
at proguard.ProGuard.main(MyApplication:538)
|
||||
Caused by: java.io.IOException: No such file or directory
|
||||
at proguard.d.q.a(MyApplication:50)
|
||||
at proguard.y.a(MyApplication:184)
|
||||
... 6 more
|
||||
|
||||
If we have saved the stack trace in a file `stacktrace.txt`, we can use
|
||||
the following command to recover the stack trace:
|
||||
|
||||
retrace mapping.txt stacktrace.txt
|
||||
|
||||
The output will correspond to the original stack trace:
|
||||
|
||||
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
|
||||
at proguard.InputReader.readInput(InputReader.java:188)
|
||||
at proguard.InputReader.readInput(InputReader.java:158)
|
||||
at proguard.InputReader.readInput(InputReader.java:136)
|
||||
at proguard.InputReader.execute(InputReader.java:66)
|
||||
at proguard.ProGuard.readInput(ProGuard.java:218)
|
||||
at proguard.ProGuard.execute(ProGuard.java:82)
|
||||
at proguard.ProGuard.main(ProGuard.java:538)
|
||||
Caused by: java.io.IOException: No such file or directory
|
||||
at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java:50)
|
||||
at proguard.InputReader.readInput(InputReader.java:184)
|
||||
... 6 more
|
||||
|
||||
### Restoring a stack trace with line numbers (verbose) {: #withverbose}
|
||||
|
||||
In the previous example, we could also use the verbose flag:
|
||||
|
||||
java -jar retrace.jar -verbose mapping.txt stacktrace.txt
|
||||
|
||||
The output will then look as follows:
|
||||
|
||||
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
|
||||
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:188)
|
||||
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,int,int,proguard.io.DataEntryReader)(InputReader.java:158)
|
||||
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,proguard.io.DataEntryReader)(InputReader.java:136)
|
||||
at proguard.InputReader.void execute(proguard.classfile.ClassPool,proguard.classfile.ClassPool)(InputReader.java:66)
|
||||
at proguard.ProGuard.void readInput()(ProGuard.java:218)
|
||||
at proguard.ProGuard.void execute()(ProGuard.java:82)
|
||||
at proguard.ProGuard.void main(java.lang.String[])(ProGuard.java:538)
|
||||
Caused by: java.io.IOException: No such file or directory
|
||||
at proguard.io.DirectoryPump.void pumpDataEntries(proguard.io.DataEntryReader)(DirectoryPump.java:50)
|
||||
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:184)
|
||||
... 6 more
|
||||
|
||||
### Restoring a stack trace without line numbers {: #without}
|
||||
|
||||
Assume for instance the application has been obfuscated using
|
||||
the following extra options, this time without preserving the line
|
||||
number tables:
|
||||
|
||||
-printmapping mapping.txt
|
||||
|
||||
A stack trace `stacktrace.txt` will then lack line number information,
|
||||
showing "Unknown source" instead:
|
||||
|
||||
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
|
||||
at proguard.y.a(Unknown Source)
|
||||
at proguard.y.a(Unknown Source)
|
||||
at proguard.y.a(Unknown Source)
|
||||
at proguard.y.a(Unknown Source)
|
||||
at proguard.ProGuard.c(Unknown Source)
|
||||
at proguard.ProGuard.a(Unknown Source)
|
||||
at proguard.ProGuard.main(Unknown Source)
|
||||
Caused by: java.io.IOException: No such file or directory
|
||||
at proguard.d.q.a(Unknown Source)
|
||||
... 7 more
|
||||
|
||||
We can still use the same command to recover the stack trace:
|
||||
|
||||
java -jar retrace.jar mapping.txt stacktrace.txt
|
||||
|
||||
The output will now list all alternative original method names for each
|
||||
ambiguous obfuscated method name:
|
||||
|
||||
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
|
||||
at proguard.InputReader.execute(InputReader.java)
|
||||
readInput(InputReader.java)
|
||||
at proguard.InputReader.execute(InputReader.java)
|
||||
readInput(InputReader.java)
|
||||
at proguard.InputReader.execute(InputReader.java)
|
||||
readInput(InputReader.java)
|
||||
at proguard.InputReader.execute(InputReader.java)
|
||||
readInput(InputReader.java)
|
||||
at proguard.ProGuard.readInput(ProGuard.java)
|
||||
at proguard.ProGuard.execute(ProGuard.java)
|
||||
optimize(ProGuard.java)
|
||||
createPrintStream(ProGuard.java)
|
||||
closePrintStream(ProGuard.java)
|
||||
fileName(ProGuard.java)
|
||||
at proguard.ProGuard.main(ProGuard.java)
|
||||
Caused by: java.io.IOException: No such file or directory
|
||||
at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java)
|
||||
readFiles(DirectoryPump.java)
|
||||
|
||||
For instance, ReTrace can't tell if the method `a` corresponds to
|
||||
`execute` or to `readInput`, so it lists both. You need to figure it out
|
||||
based on your knowledge of the application. Having line numbers and
|
||||
unambiguous names clearly is a lot easier, so you should consider
|
||||
[preserving the line numbers](../configuration/examples.md#stacktrace) when you
|
||||
obfuscate your application.
|
||||
|
||||
|
||||
## Specifications {: #specifications }
|
||||
|
||||
A mapping file contains the original names and the obfuscated names of
|
||||
classes, fields, and methods. ProGuard can write out such a file while
|
||||
obfuscating an application or a library, with the option
|
||||
[`-printmapping`](../configuration/usage.md#printmapping). ReTrace requires the mapping file
|
||||
to restore obfuscated stack traces to more readable versions. It is a readable
|
||||
file with UTF-8 encoding, so you can also look up names in an ordinary text
|
||||
viewer. The format is pretty self-explanatory, but we describe its details
|
||||
here.
|
||||
|
||||
A mapping file contains a sequence of records of the following form:
|
||||
|
||||
classline
|
||||
fieldline *
|
||||
methodline *
|
||||
|
||||
A `classline`, with a trailing colon, specifies a class and its obfuscated
|
||||
name:
|
||||
|
||||
originalclassname -> obfuscatedclassname:
|
||||
|
||||
A `fieldline`, with 4 leading spaces, specifies a field and its obfuscated
|
||||
name:
|
||||
|
||||
originalfieldtype originalfieldname -> obfuscatedfieldname
|
||||
|
||||
A `methodline`, with 4 leading spaces, specifies a method and its obfuscated
|
||||
name:
|
||||
|
||||
[startline:endline:]originalreturntype [originalclassname.]originalmethodname(originalargumenttype,...)[:originalstartline[:originalendline]] -> obfuscatedmethodname
|
||||
|
||||
- An asterisk "*" means the line may occur any number of times.
|
||||
- Square brackets "\[\]" mean that their contents are optional.
|
||||
- Ellipsis dots "..." mean that any number of the preceding items may be specified.
|
||||
- The colon ":", the separator ".", and the arrow "->" are literal tokens.
|
||||
|
||||
### Example
|
||||
|
||||
The following snippet gives an impression of the structure of a mapping file:
|
||||
|
||||
com example.application.ArgumentWordReader -> com.example.a.a:
|
||||
java.lang.String[] arguments -> a
|
||||
int index -> a
|
||||
36:57:void <init>(java.lang.String[],java.io.File) -> <init>
|
||||
64:64:java.lang.String nextLine() -> a
|
||||
72:72:java.lang.String lineLocationDescription() -> b
|
||||
com.example.application.Main -> com.example.application.Main:
|
||||
com.example.application.Configuration configuration -> a
|
||||
50:66:void <init>(com.example.application.Configuration) -> <init>
|
||||
74:228:void execute() -> a
|
||||
2039:2056:void com.example.application.GPL.check():39:56 -> a
|
||||
2039:2056:void execute():76 -> a
|
||||
2236:2252:void printConfiguration():236:252 -> a
|
||||
2236:2252:void execute():80 -> a
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
3040:3042:void printConfiguration():243 -> a
|
||||
3040:3042:void execute():80 -> a
|
||||
3260:3268:void readInput():260:268 -> a
|
||||
3260:3268:void execute():97 -> a
|
||||
|
||||
|
||||
You can see the names of classes and their fields and methods:
|
||||
|
||||
- The fields and methods are listed in ProGuard configuration format (javap
|
||||
format), with descriptors that have return types and argument types but no
|
||||
argument names. In the above example:
|
||||
|
||||
void <init>(java.lang.String[],java.io.File)
|
||||
|
||||
refers to a constructor with a `String` array argument and a `File`
|
||||
argument.
|
||||
|
||||
- A method may have a leading line number range, if it is known from the
|
||||
original source code (see [Producing useful obfuscated stack
|
||||
traces](../configuration/examples.md#stacktrace) in the Examples section). Unlike method
|
||||
names, line numbers are unique within a class, so ReTrace can resolve lines
|
||||
in a stack trace without ambiguities. For example:
|
||||
|
||||
74:228:void execute()
|
||||
|
||||
refers to a method `execute`, defined on lines 74 to 228.
|
||||
|
||||
- The obfuscated method name follows the arrow. For example:
|
||||
|
||||
74:228:void execute() -> a
|
||||
|
||||
shows that method `execute` has been renamed to `a`. Multiple fields and
|
||||
methods can get the same obfuscated names, as long as their descriptors
|
||||
are different.
|
||||
|
||||
### Inlined methods
|
||||
|
||||
The mapping file accounts for the added complexity of inlined methods (as of
|
||||
ProGuard/ReTrace version 5.2). The optimization step may inline methods
|
||||
into other methods — recursively even. A single line in an obfuscated
|
||||
stack trace can then correspond to multiple lines in the original stack trace:
|
||||
the line that throws the exception followed by one or more nested method
|
||||
calls. In such cases, the mapping file repeats the leading line number range
|
||||
on subsequent lines. For example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
3040:3042:void printConfiguration():243 -> a
|
||||
3040:3042:void execute():80 -> a
|
||||
|
||||
- The subsequent lines correspond to the subsequent lines of the original
|
||||
stack trace. For example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
3040:3042:void printConfiguration():243 -> a
|
||||
3040:3042:void execute():80 -> a
|
||||
|
||||
refers to method `createPrintWriterOut` called from and inlined in
|
||||
`printConfiguration`, in turn called from and inlined in method `execute`.
|
||||
|
||||
- An original method name may have a preceding class name, if the method
|
||||
originates from a different class. For example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
|
||||
shows that method `createPrintWriterOut` was originally defined in class
|
||||
`PrintWriterUtil`.
|
||||
|
||||
- A single trailing line number corresponds to an inlined method call. For
|
||||
example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
3040:3042:void printConfiguration():243 -> a
|
||||
3040:3042:void execute():80 -> a
|
||||
|
||||
specifies that method `execute` called `printConfiguration` on line 80,
|
||||
and `printconfiguration` called `createPrintWriterOut` on line 243.
|
||||
|
||||
- A traling line number range corresponds to the final inlined method body.
|
||||
For example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
|
||||
shows that method `createPrintWriterOut` covered lines 40 to 42.
|
||||
|
||||
- The leading line number range is synthetic, to avoid ambiguities with other
|
||||
code in the same class. ProGuard makes up the range, but tries to make it
|
||||
similar-looking to the original code (by adding offsets that are multiples
|
||||
of 1000), for convenience. For example:
|
||||
|
||||
3040:3042:java.io.PrintWriter com.example.application.util.PrintWriterUtil.createPrintWriterOut(java.io.File):40:42 -> a
|
||||
|
||||
created synthetic range 3040:3042 in the bytecode of class `Main` to be
|
||||
unique but still resemble source code range 40:42 in class
|
||||
`PrintWriterUtil`.
|
||||
|
||||
Tools that don't account for these repeated line number ranges, like older
|
||||
versions of ReTrace, may still degrade gracefully by outputting the subsequent
|
||||
lines without interpreting them.
|
@ -1,18 +0,0 @@
|
||||
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.
|
@ -1,628 +0,0 @@
|
||||
While preparing a configuration for processing your code, you may bump
|
||||
into a few problems. The following sections discuss some common issues
|
||||
and solutions:
|
||||
|
||||
!!! tip
|
||||
Whenever you don't find the solution for your issue on this page, the [***Guardsquare Community***](https://community.guardsquare.com/) might be the place to check for an answer or post a question.
|
||||
|
||||
|
||||
|
||||
## Problems while processing {: #processing}
|
||||
|
||||
ProGuard may print out some notes and non-fatal warnings:
|
||||
|
||||
**Note: can't find dynamically referenced class ...** {: #dynamicalclass}
|
||||
: ProGuard can't find a class or interface that your code is accessing by
|
||||
means of introspection. You should consider adding the jar that contains
|
||||
this class.
|
||||
|
||||
**Note: ... calls '(...)Class.forName(variable).newInstance()'** {: #dynamicalclasscast}
|
||||
: Your code uses reflection to dynamically create class instances, with a
|
||||
construct 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`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Note: ... accesses a field/method '...' dynamically** {: #dynamicalclassmember}
|
||||
: Your code uses reflection to find a fields or a method, with a construct
|
||||
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`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Note: ... calls 'Class.get...'**, **'Field.get...'**, or **'Method.get...'** {: #attributes}
|
||||
: Your code uses reflection to access metadata from the code, with an
|
||||
invocation like "`class.getAnnotations()`". You then generally need to
|
||||
preserve optional [class file attributes](../configuration/attributes.md), which ProGuard
|
||||
removes by default. The attributes contain information about annotations,
|
||||
enclosing classes, enclosing methods, etc. In a summary in the log, ProGuard
|
||||
provides a suggested configuration, like [`-keepattributes
|
||||
*Annotation*`](../configuration/usage.md#keepattributes). If you're sure the attributes are
|
||||
not necessary, you can switch off these notes by specifying the
|
||||
[`-dontnote`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Note: the configuration refers to the unknown class '...'** {: #unknownclass}
|
||||
: Your configuration refers to the name of a class that is not present in
|
||||
the program jars or library jars. You should check whether the name is
|
||||
correct. Notably, you should make sure that you always specify
|
||||
fully-qualified names, not forgetting the package names.
|
||||
|
||||
**Note: the configuration keeps the entry point '...', but not the descriptor class '...'** {: #descriptorclass}
|
||||
: Your configuration contains a [`-keep`](../configuration/usage.md#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
|
||||
automatically keep such descriptor classes with the `-keep` option modifier
|
||||
[`includedescriptorclasses`](../configuration/usage.md#includedescriptorclasses)
|
||||
(`-keep,includedescriptorclasses` ...). You can switch off these notes by
|
||||
specifying the [`-dontnote`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Note: the configuration explicitly specifies '...' to keep library class '...'** {: #libraryclass}
|
||||
: Your configuration contains a [`-keep`](../configuration/usage.md#keep) option to preserve
|
||||
the given library class. However, you don't need to keep any library
|
||||
classes. ProGuard always leaves underlying libraries unchanged. You can
|
||||
switch off these notes by specifying the [`-dontnote`](../configuration/usage.md#dontnote)
|
||||
option.
|
||||
|
||||
**Note: the configuration doesn't specify which class members to keep for class '...'** {: #classmembers}
|
||||
: Your configuration contains a
|
||||
[`-keepclassmembers`](../configuration/usage.md#keepclassmembers)/[`-keepclasseswithmembers`](../configuration/usage.md#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 should also consider if you just need the more common
|
||||
[`-keep`](../configuration/usage.md#keep) option, which preserves all specified classes *and*
|
||||
class members. The [overview of all `keep` options](../configuration/usage.md#keepoverview)
|
||||
can help. You can switch off these notes by specifying the
|
||||
[`-dontnote`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Note: the configuration specifies that none of the methods of class '...' have any side effects** {: #nosideeffects}
|
||||
: Your configuration contains an option
|
||||
[`-assumenosideeffects`](../configuration/usage.md#assumenosideeffects) to indicate that the
|
||||
specified methods don't have any side effects. However, the configuration
|
||||
tries to match *all* methods, by using a wildcard like "`*;`". This includes
|
||||
methods from `java.lang.Object`, such as `wait()` and `notify()`. Removing
|
||||
invocations of those methods will most likely break your application. You
|
||||
should list the methods without side effects more conservatively. You can
|
||||
switch off these notes by specifying the [`-dontnote`](../configuration/usage.md#dontnote)
|
||||
option.
|
||||
|
||||
**Note: duplicate definition of program/library class** {: #duplicateclass}
|
||||
: 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`](../configuration/usage.md#dontnote) option.
|
||||
|
||||
**Warning: can't write resource ... Duplicate zip entry** {: #duplicatezipentry}
|
||||
: 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**<br/>**Warning: can't find referenced class** {: #unresolvedclass}
|
||||
: 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 warning lists both
|
||||
the referencing class(es) and the missing referenced class(es). There can be
|
||||
a few reasons, with their own solutions:
|
||||
|
||||
1. 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`](../configuration/usage.md#injars), otherwise
|
||||
you should specify it with [`-libraryjars`](../configuration/usage.md#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 in `lib/rt.jar` (`vm.jar` for IBM's JVM, and
|
||||
`classes.jar` in MacOS X) or as of Java 9, `jmods/java.base.jmod`.
|
||||
|
||||
2. 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](../configuration/usage.md#filters) the
|
||||
*referencing* class or classes from the input, with a filter
|
||||
like
|
||||
"`-injars myapplication.jar(!somepackage/SomeUnusedReferencingClass.class)`".
|
||||
DexGuard 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
|
||||
"`-libraryjars mylibrary.jar(!someunusedpackage/**)`".
|
||||
|
||||
3. If you don't feel like filtering out the problematic classes,
|
||||
you can try your luck with the
|
||||
[`-ignorewarnings`](../configuration/usage.md#ignorewarnings) option, or even
|
||||
the [`-dontwarn`](../configuration/usage.md#dontwarn) option. Only use these
|
||||
options if you really know what you're doing though.
|
||||
|
||||
**Error: Can't find any super classes of ... (not even immediate super class ...)**
|
||||
**Error: Can't find common super class of ... and ...** {: #superclass}
|
||||
: It seems like you tried to avoid the warnings from the previous paragraph
|
||||
by specifying [`-ignorewarnings`](../configuration/usage.md#ignorewarnings) or
|
||||
[`-dontwarn`](../configuration/usage.md#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`](../configuration/usage.md#injars) option: "`-injars
|
||||
myapplication.jar(!somepackage/SomeUnusedClass.class)`". As a final
|
||||
solution, you could switch off optimization
|
||||
([`-dontoptimize`](../configuration/usage.md#dontoptimize)) and preverification
|
||||
([`-dontpreverify`](../configuration/usage.md#dontpreverify)).
|
||||
|
||||
**Warning: can't find referenced field/method '...' in program class ...** {: #unresolvedprogramclassmember}
|
||||
: A program class is referring to a field or a method that is missing from
|
||||
another program class. The warning lists both the referencing class and the
|
||||
missing referenced class member. 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: can't find referenced field/method '...' in library class ...** {: #unresolvedlibraryclassmember}
|
||||
: A program class is referring to a field or a method that is missing from a
|
||||
library class. The warning lists both the referencing class and the missing
|
||||
referenced class member. 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.
|
||||
|
||||
1. 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.
|
||||
|
||||
2. 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.
|
||||
|
||||
Alternatively, you may get away with ignoring the inconsistency
|
||||
with the options [`-ignorewarnings`](../configuration/usage.md#ignorewarnings)
|
||||
or even [`-dontwarn`](../configuration/usage.md#dontwarn).
|
||||
|
||||
**Warning: can't find enclosing class/method** {: #unresolvedenclosingmethod}
|
||||
: 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 ...** {: #dependency}
|
||||
: 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`](../configuration/usage.md#injars)) and library code
|
||||
(specified with [`-libraryjars`](../configuration/usage.md#libraryjars)), and try again.
|
||||
|
||||
**Warning: class file ... unexpectedly contains class ...** {: #unexpectedclass}
|
||||
: 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 the `WEB-INF/lib` directory. If you don't mind these classes not being
|
||||
written to the output, you can specify the
|
||||
[`-ignorewarnings`](../configuration/usage.md#ignorewarnings) option, or even the
|
||||
[`-dontwarn`](../configuration/usage.md#dontwarn) option.
|
||||
|
||||
**Warning: ... is not being kept as ..., but remapped to ...** {: #mappingconflict1}
|
||||
: There is a conflict between a [`-keep`](../configuration/usage.md#keep) option and the
|
||||
mapping file specified with an [`-applymapping`](../configuration/usage.md#applymapping)
|
||||
option, 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`](../configuration/usage.md#ignorewarnings) option, or even the
|
||||
[`-dontwarn`](../configuration/usage.md#dontwarn) option.
|
||||
|
||||
**Warning: field/method ... can't be mapped to ...** {: #mappingconflict2}
|
||||
: There is a conflict between some new program code and the mapping file
|
||||
specified with an [`-applymapping`](../configuration/usage.md#applymapping) option, 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`](../configuration/usage.md#ignorewarnings) option, or even the
|
||||
[`-dontwarn`](../configuration/usage.md#dontwarn) option. Note that you should always use the
|
||||
[`-useuniqueclassmembernames`](../configuration/usage.md#useuniqueclassmembernames) option in
|
||||
the initial obfuscation step, in order to reduce the risk of conflicts.
|
||||
|
||||
**Error: Unsupported class version number** {: #unsupportedclassversion}
|
||||
: 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](https://github.com/Guardsquare/proguard/releases) if there is a more
|
||||
recent release.
|
||||
|
||||
**Error: You have to specify [`-keep`](../configuration/usage.md#keep) options**
|
||||
: You either forgot to specify [`-keep`](../configuration/usage.md#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](../configuration/usage.md#filename). 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, 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`.
|
||||
|
||||
As of Java 9, the runtime classes are packaged in
|
||||
`<java.home>/jmods/java.base.jmod` and other modules next to it.
|
||||
|
||||
**Error: Can't read ...** {: #cantread}
|
||||
: 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 ...** {: #cantwrite}
|
||||
: 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](http://bugs.sun.com/view_bug.do?bug_id=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** {: #outofmemoryerror}
|
||||
: You can try increasing the heap size of the Java virtual machine, with the
|
||||
usual `-Xmx` option:
|
||||
|
||||
- In Java, specify the option as an argument to the JVM: `java -Xmx1024m`
|
||||
- In Ant, set the environment variable `ANT_OPTS=-Xmx1024m`
|
||||
- In Gradle, set the environment variable `GRADLE_OPTS=-Xmx1024m`
|
||||
- In Maven, set the environment variable `MAVEN_OPTS=-Xmx1024m`
|
||||
- In Eclipse, add the line `-Xmx1024m` to the file `eclipse.ini` inside
|
||||
your Eclipse install.
|
||||
|
||||
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.
|
||||
|
||||
**StackOverflowError** {: #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](http://bugs.sun.com/view_bug.do?bug_id=4362291). As a result,
|
||||
this solution will only work when running ProGuard in a different thread,
|
||||
e.g. from its GUI.
|
||||
|
||||
**Unexpected error** {: #unexpectederror}
|
||||
: 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`](../configuration/usage.md#dontoptimize) option. In any case,
|
||||
please report the problem, preferably with the simplest example that causes
|
||||
ProGuard to crash.
|
||||
|
||||
**Otherwise...** {: #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 {: #afterprocessing}
|
||||
|
||||
If ProGuard seems to run fine, but your processed code doesn't look
|
||||
right, there might be a couple of reasons:
|
||||
|
||||
**Disappearing classes** {: #disappearingclasses}
|
||||
: 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`](../configuration/usage.md#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 the `WEB-INF/lib` directory.
|
||||
|
||||
**Classes or class members not being kept** {: #notkept}
|
||||
: 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`](../configuration/usage.md#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 *`".
|
||||
|
||||
**Class names not being obfuscated** {: #classnamesnotobfuscated}
|
||||
: If the names of some classes in your obfuscated code aren't obfuscated, you
|
||||
should first check all your configuration files. Chances are that some
|
||||
`-keep` option is preserving the original names. These options may be hiding
|
||||
in your own configuration files or in configuration files from libraries.
|
||||
|
||||
**Field names not being obfuscated** {: #fieldnamesnotobfuscated}
|
||||
: If the names of some fields in your obfuscated code aren't obfuscated, this
|
||||
may be due to `-keep` options preserving the original names, for the sake of
|
||||
libraries like GSON. Such libraries perform reflection on the fields. If the
|
||||
names were obfuscated, the resulting JSON strings would come out obfuscated
|
||||
as well, which generally breaks persistence of the data or communication
|
||||
with servers.
|
||||
|
||||
**Method names not being obfuscated** {: #methodnamesnotobfuscated}
|
||||
: If the names of some methods in your obfuscated code aren't obfuscated, this
|
||||
is most likely because they extend or implement method names in the
|
||||
underlying runtime libraries. Since the runtime libraries are not obfuscated,
|
||||
any corresponding names in the application code can't be obfuscated either,
|
||||
since they must remain consistent.
|
||||
|
||||
**Variable names not being obfuscated** {: #variablenamesnotobfuscated}
|
||||
: 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` or
|
||||
`LocalVariableTypeTable` attributes.
|
||||
|
||||
## 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:
|
||||
|
||||
**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`](../configuration/usage.md#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`](../configuration/usage.md#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.
|
||||
|
||||
Note that it is no longer necessary to use an external preverifier. With
|
||||
the [`-microedition`](../configuration/usage.md#microedition) option, ProGuard will
|
||||
preverify the class files for Java Micro Edition.
|
||||
|
||||
## Problems at run-time {: #runtime}
|
||||
|
||||
If ProGuard runs fine, but your processed application doesn't work,
|
||||
there might be several reasons:
|
||||
|
||||
**Stack traces without class names or line numbers** {: #stacktraces}
|
||||
: 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** {: #noclassdeffounderror}
|
||||
: Your class path is probably incorrect. It should at least contain all
|
||||
library jars and, of course, your processed program jar.
|
||||
|
||||
**ClassNotFoundException** {: #classnotfoundexception}
|
||||
: Your code is probably calling `Class.forName`, trying to create the
|
||||
missing class dynamically. ProGuard can only detect constant name arguments,
|
||||
like `Class.forName("com.example.MyClass")`. For variable name arguments
|
||||
like `Class.forName(someClass)`, you have to keep all possible classes using
|
||||
the appropriate [`-keep`](../configuration/usage.md#keep) option, e.g. "`-keep class
|
||||
com.example.MyClass`" or "`-keep class * implements
|
||||
com.example.MyInterface`". While setting up your configuration, you can
|
||||
specify the option
|
||||
[`-addconfigurationdebugging`](../configuration/usage.md#addconfigurationdebugging) to help
|
||||
track down these cases at run-time and let the instrumented code suggest
|
||||
settings for them.
|
||||
|
||||
**NoSuchFieldException** {: #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 using the appropriate
|
||||
[`-keep`](../configuration/usage.md#keep) option, e.g. "`-keepclassmembers class
|
||||
com.example.MyClass { int myField; }`". While setting up your configuration,
|
||||
you can specify the option
|
||||
[`-addconfigurationdebugging`](../configuration/usage.md#addconfigurationdebugging) to help
|
||||
track down these cases at run-time and let the instrumented code suggest
|
||||
settings for them.
|
||||
|
||||
**NoSuchMethodException** {: #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 using the appropriate
|
||||
[`-keep`](../configuration/usage.md#keep) option, e.g. "`-keepclassmembers class
|
||||
com.example.MyClass { void myMethod(); }`". While setting up your
|
||||
configuration, you can specify the option
|
||||
[`-addconfigurationdebugging`](../configuration/usage.md#addconfigurationdebugging) to help
|
||||
track down these cases at run-time and let the instrumented code suggest
|
||||
settings for them. More specifically, if the method reported as missing is
|
||||
`values` or `valueOf`, you probably have to keep some methods related to
|
||||
[enumerations](../configuration/examples.md#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`](../configuration/usage.md#adaptresourcefilenames) and/or
|
||||
[`-adaptresourcefilecontents`](../configuration/usage.md#adaptresourcefilecontents).
|
||||
Furthermore, directory entries in jar files aren't copied, unless you
|
||||
specify the option [`-keepdirectories`](../configuration/usage.md#keepdirectories). Note that
|
||||
Sun advises against calling `Class.getResource()` for directories (Sun Bug
|
||||
\#4761949](http://bugs.sun.com/view_bug.do?bug_id=4761949)).
|
||||
|
||||
**Disappearing annotations** {: #disappearingannotations}
|
||||
: 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** {: #invalidjarfile}
|
||||
: 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** {: #invalidjarindexexception}
|
||||
: 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`](../configuration/usage.md#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`](../configuration/usage.md#overloadaggressively).
|
||||
|
||||
**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`](../configuration/usage.md#useuniqueclassmembernames) option.
|
||||
It avoids overloading class member names, which triggers a bug in their java
|
||||
virtual machine. You might also try using the
|
||||
[`-dontusemixedcaseclassnames`](../configuration/usage.md#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** {: #disappearingloops}
|
||||
: 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`](../configuration/usage.md#dontoptimize) option.
|
||||
|
||||
**SecurityException: SHA1 digest error** {: #securityexception}
|
||||
: You may have forgotten to sign your program jar *after* having processed
|
||||
it with ProGuard.
|
||||
|
||||
**ClassCastException: class not an enum**<br/>**IllegalArgumentException: class not an enum type** {: #classcastexception}
|
||||
: 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](../configuration/examples.md#enumerations).
|
||||
|
||||
**ArrayStoreException: sun.reflect.annotation.EnumConstantNotPresentExceptionProxy** {: #arraystoreexception}
|
||||
: 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.
|
||||
|
||||
**IllegalArgumentException: methods with same signature but incompatible return types** {: #illegalargumentexception}
|
||||
: You are probably running some code that has been obfuscated with the
|
||||
[`-overloadaggressively`](../configuration/usage.md#overloadaggressively) option. The class
|
||||
`java.lang.reflect.Proxy` can't handle classes that contain methods with the
|
||||
same names and signatures, but different return types. Its method
|
||||
`newProxyInstance` then throws this exception. You can avoid the problem by
|
||||
not using the option.
|
||||
|
||||
**CompilerError: duplicate addition** {: #compilererror}
|
||||
: You are probably compiling or running some code that has been obfuscated
|
||||
with the [`-overloadaggressively`](../configuration/usage.md#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** {: #classformaterror1}
|
||||
: You are probably processing some code that has been obfuscated before with
|
||||
the [`-overloadaggressively`](../configuration/usage.md#overloadaggressively) option. You
|
||||
should then use the same option again in the second processing round.
|
||||
|
||||
**ClassFormatError: Invalid index in LocalVariableTable in class file** {: #classformaterror2}
|
||||
: 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.
|
||||
|
||||
**NullPointerException: create returned null** (Dagger)<br/>**IllegalStateException: Module adapter for class ... could not be loaded. Please ensure that code generation was run for this module.**<br/>**IllegalStateException: Could not load class ... needed for binding members/...** {:#dagger}
|
||||
: Dagger 1 relies on reflection to combine annotated base classes and their
|
||||
corresponding generated classes. DexGuard's default configuration already
|
||||
preserves the generated classes, but you still preserve the annotated base
|
||||
classes in your project-specific configuration. This is explained in some
|
||||
more detail in the [Dagger example](../configuration/examples.md#dagger).
|
||||
|
||||
**NoSuchMethodError** or **AbstractMethodError** {: #nosuchmethoderror}
|
||||
: 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](#disappearingclasses) 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** {: #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`](../configuration/usage.md#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.
|
@ -1,43 +0,0 @@
|
||||
**ProGuard** successfully processes any Java bytecode, ranging from small
|
||||
applications 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](http://www.oracle.com/technetwork/java/javame/index.html), 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](http://www.javadocking.com/), 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](http://www.clarkware.com/software/JDepend.html), a Java quality metrics tool | 57 K | 36 K | 33 K | 28 K | 51 % | 6 s | 24 M
|
||||
| [the run-time classes](http://www.oracle.com/technetwork/java/javase/overview/index.html) from Oracle's Java 6 | 53 M | 23 M | 22 M | 18 M | 66 % | 16 min | 270 M
|
||||
| [Tomcat](http://tomcat.apache.org/), the Apache servlet container | 1.1 M | 466 K | 426 K | 295 K | 74 % | 17 s | 44 M
|
||||
| [JavaNCSS](http://javancss.codehaus.org/), a Java source metrics tool | 632 K | 242 K | 212 K | 152 K | 75 % | 20 s | 36 M
|
||||
| [Ant](http://ant.apache.org/), 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.
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name="HelloWorldActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -1,75 +0,0 @@
|
||||
// This build file illustrates how to apply ProGuard in the Android build
|
||||
// process with AGP < 7, by swapping the built-in version of ProGuard for a newer version.
|
||||
|
||||
// This process relies on setting `android.enableR8=false` in `gradle.properties`,
|
||||
// which is deprecated. For AGP7, please see the `android-plugin` example.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal() // For local testing
|
||||
google() // For the Android plugin.
|
||||
mavenCentral() // For anything else.
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||
}
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
// Override the default version of ProGuard with the most recent one.
|
||||
dependencySubstitution {
|
||||
substitute module('net.sf.proguard:proguard-gradle') with module('com.guardsquare:proguard-gradle:7.3.0')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
storePassword 'android'
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 11
|
||||
targetSdkVersion 28
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
minifyEnabled false
|
||||
shrinkResources false
|
||||
}
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
|
||||
proguardFile 'proguard-project.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google() // For the Android plugin.
|
||||
mavenCentral() // For anything else.
|
||||
}
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user