add export to c# button

This commit is contained in:
Mystikfluu 2023-04-13 07:10:18 +02:00
parent a1a397d06d
commit 1a20bea369
164 changed files with 14362 additions and 1 deletions

1
.idea/encodings.xml generated
View File

@ -2,5 +2,6 @@
<project version="4"> <project version="4">
<component name="Encoding"> <component name="Encoding">
<file url="file://$PROJECT_DIR$/data/colors.txt" charset="windows-1252" /> <file url="file://$PROJECT_DIR$/data/colors.txt" charset="windows-1252" />
<file url="file://$PROJECT_DIR$/data/places.txt" charset="windows-1252" />
</component> </component>
</project> </project>

View File

@ -80,6 +80,7 @@ public class B3
public final RadioButton msSqlStyle; public final RadioButton msSqlStyle;
public final CheckBox generateRelationalModelCB; public final CheckBox generateRelationalModelCB;
public final Button saveSQLScriptBTN; public final Button saveSQLScriptBTN;
public final Button saveCSScriptBTN;
public final CheckBox generateInsertsCB; public final CheckBox generateInsertsCB;
public final CheckBox singleInsertStatementCB; public final CheckBox singleInsertStatementCB;
public final CheckBox addCurrentDateToDatabaseNameCB; public final CheckBox addCurrentDateToDatabaseNameCB;
@ -743,6 +744,22 @@ public class B3
} }
}); });
this.saveCSScriptBTN = new Button("Generate/Save C# script");
this.saveCSScriptBTN.setTooltip(new Tooltip("The ddl-script will be generated and saved into a file"));
this.saveCSScriptBTN.setMaxWidth(Double.MAX_VALUE);
setMouseHandler(this.saveCSScriptBTN);
GridPane.setFillWidth(this.saveCSScriptBTN, Boolean.TRUE);
this.saveCSScriptBTN.setBackground(new Background(new BackgroundFill(C2.ButtonBackgroundColor, CornerRadii.EMPTY, Insets.EMPTY)));
this.saveCSScriptBTN.setOnAction(arg0 -> {
if (B3.this.generateRelationalModelCB.isSelected()) {
try {
B3.this.saveSQLScript();
} catch (ZZ20 ignored) {
}
}
});
this.generateInsertsCB = new CheckBox("Generate insert statement"); this.generateInsertsCB = new CheckBox("Generate insert statement");
this.generateInsertsCB.setTooltip(new Tooltip("If selected, insert statements are generated in the ddl-script")); this.generateInsertsCB.setTooltip(new Tooltip("If selected, insert statements are generated in the ddl-script"));
@ -878,7 +895,14 @@ public class B3
box.getChildren().addAll(this.addCurrentDateToDatabaseNameCB, this.generateInsertsCB, this.singleInsertStatementCB, this.saveSQLScriptBTN); box.getChildren().addAll(this.addCurrentDateToDatabaseNameCB, this.generateInsertsCB, this.singleInsertStatementCB, this.saveSQLScriptBTN);
TitledPane createddl = new TitledPane("Create DDL", box); TitledPane createddl = new TitledPane("Create DDL", box);
createddl.setExpanded(false); createddl.setExpanded(false);
this.buttonPane.add(createddl, 0, ri, 2, 1); this.buttonPane.add(createddl, 0, ri++, 2, 1);
VBox csbox = new VBox(10.0D);
csbox.getChildren().addAll(saveCSScriptBTN);
TitledPane createcsharp = new TitledPane("Create C# Code", csbox);
createcsharp.setExpanded(false);
this.buttonPane.add(createcsharp, 0, ri, 2, 1);
this.statusInformation = new TextField("Creation Mode: entity-set -> press left mouse button on working area -> enter name of entity-set -> press enter key"); this.statusInformation = new TextField("Creation Mode: entity-set -> press left mouse button on working area -> enter name of entity-set -> press enter key");
this.statusInformation.setEditable(false); this.statusInformation.setEditable(false);

View File

@ -7,6 +7,10 @@
<excludeFolder url="file://$MODULE_DIR$/lib" /> <excludeFolder url="file://$MODULE_DIR$/lib" />
<excludeFolder url="file://$MODULE_DIR$/.idea" /> <excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/data" /> <excludeFolder url="file://$MODULE_DIR$/data" />
<excludeFolder url="file://$MODULE_DIR$/proguard" />
<excludePattern pattern=".gitignore" />
<excludePattern pattern="*.bat" />
<excludePattern pattern="*.iml" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

BIN
noEasyDB_optimized.jar Normal file

Binary file not shown.

BIN
noEasyDB_optimized_old.jar Normal file

Binary file not shown.

1
optimize.bat Normal file
View File

@ -0,0 +1 @@
proguard\bin\proguard.bat -verbose -injar out/artifacts/noEasyDB/noEasyDB.jar -outjars noEasyDB_optimized.jar -keep class at.fos.ermodel.gui.A1 { *; } -libraryjars "<java.home>/jmods/java.desktop.jmod;<java.home>/jmods/java.base.jmod;<java.home>/jmods/javafx.base.jmod;<java.home>/jmods/javafx.graphics.jmod;<java.home>/jmods/javafx.controls.jmod;<java.home>/jmods/javafx.swing.jmod"

339
proguard/LICENSE Normal file
View File

@ -0,0 +1,339 @@
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.

14
proguard/bin/proguard.bat Normal file
View File

@ -0,0 +1,14 @@
@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" %*

24
proguard/bin/proguard.sh Normal file
View File

@ -0,0 +1,24 @@
#!/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" "$@"

View File

@ -0,0 +1,14 @@
@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" %*

View File

@ -0,0 +1,27 @@
#!/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" "$@"

14
proguard/bin/retrace.bat Normal file
View File

@ -0,0 +1,14 @@
@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" %*

24
proguard/bin/retrace.sh Normal file
View File

@ -0,0 +1,24 @@
#!/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" "$@"

View File

@ -0,0 +1,19 @@
**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.

36
proguard/docs/index.md Normal file
View File

@ -0,0 +1,36 @@
**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.

212
proguard/docs/manual/FAQ.md Normal file
View File

@ -0,0 +1,212 @@
## 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.

View File

@ -0,0 +1,71 @@
# 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
```

View File

@ -0,0 +1,176 @@
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

View File

@ -0,0 +1,221 @@
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

View File

@ -0,0 +1,40 @@
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/).

View File

@ -0,0 +1,126 @@
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.

View File

@ -0,0 +1,6 @@
## 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.

View File

@ -0,0 +1,83 @@
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.

View File

@ -0,0 +1,259 @@
# 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.

View File

@ -0,0 +1,36 @@
# 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.

View File

@ -0,0 +1,26 @@
**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.

View File

@ -0,0 +1,78 @@
# 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)

View File

@ -0,0 +1,141 @@
## 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
'**&lt;**' and '**&gt;**'.
- 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

View File

@ -0,0 +1,454 @@
**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 `&lt;` and `&gt;`
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.

View File

@ -0,0 +1,470 @@
**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/**')
.....
}
}
```

View File

@ -0,0 +1,250 @@
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.

View File

@ -0,0 +1,54 @@
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).

View File

@ -0,0 +1,8 @@
# 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>
![](appsweep.png)
</center>

View File

@ -0,0 +1,7 @@
# 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>

View File

@ -0,0 +1,382 @@
# 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 &mdash; 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.

View File

@ -0,0 +1,18 @@
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.

View File

@ -0,0 +1,628 @@
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.

43
proguard/docs/results.md Normal file
View File

@ -0,0 +1,43 @@
**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.

View File

@ -0,0 +1,17 @@
<?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>

View File

@ -0,0 +1,75 @@
// 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.

View File

@ -0,0 +1,4 @@
# Make sure that we use ProGuard instead of R8.
android.enableR8=false
android.enableR8.libraries=false

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -0,0 +1,183 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

View File

@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,127 @@
###############################################################################
# General settings.
###############################################################################
-verbose
# We can debug the ProGuard configuration by instrumenting the code and
# checking the log for feedback. Disable the option again for actual releases!
#-addconfigurationdebugging
# We can also disable the individual processing steps.
#-dontshrink
#-dontoptimize
#-dontobfuscate
# Specifically target Android.
-android
###############################################################################
# Settings to handle reflection in the code.
###############################################################################
# Preserve annotated and generated classes for Dagger.
-keepclassmembers,allowobfuscation class * {
@dagger.** *;
}
-keep class **$$ModuleAdapter
-keep class **$$InjectAdapter
-keep class **$$StaticInjection
-if class **$$ModuleAdapter
-keep class <1>
-if class **$$InjectAdapter
-keep class <1>
-if class **$$StaticInjection
-keep class <1>
-keepnames class dagger.Lazy
# Preserve annotated and generated classes for Butterknife.
-keep class **$$ViewBinder {
public static void bind(...);
public static void unbind(...);
}
-if class **$$ViewBinder
-keep class <1>
-keep class **_ViewBinding {
<init>(<1>, android.view.View);
}
-if class **_ViewBinding
-keep class <1>
# Preserve fields that are serialized with GSON.
#-keepclassmembers class com.example.SerializedClass1,
# com.example.SerializedClass2 {
# <fields>;
#}
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation @interface com.google.gson.annotations.**
###############################################################################
# Further optimizations.
###############################################################################
# If you wish, you can let the optimization step remove Android logging calls.
#-assumenosideeffects class android.util.Log {
# public static boolean isLoggable(java.lang.String, int);
# public static int v(...);
# public static int i(...);
# public static int w(...);
# public static int d(...);
# public static int e(...);
#}
# In that case, it's especially useful to also clean up any corresponding
# string concatenation calls.
-assumenoexternalsideeffects class java.lang.StringBuilder {
public java.lang.StringBuilder();
public java.lang.StringBuilder(int);
public java.lang.StringBuilder(java.lang.String);
public java.lang.StringBuilder append(java.lang.Object);
public java.lang.StringBuilder append(java.lang.String);
public java.lang.StringBuilder append(java.lang.StringBuffer);
public java.lang.StringBuilder append(char[]);
public java.lang.StringBuilder append(char[], int, int);
public java.lang.StringBuilder append(boolean);
public java.lang.StringBuilder append(char);
public java.lang.StringBuilder append(int);
public java.lang.StringBuilder append(long);
public java.lang.StringBuilder append(float);
public java.lang.StringBuilder append(double);
public java.lang.String toString();
}
-assumenoexternalreturnvalues class java.lang.StringBuilder {
public java.lang.StringBuilder append(java.lang.Object);
public java.lang.StringBuilder append(java.lang.String);
public java.lang.StringBuilder append(java.lang.StringBuffer);
public java.lang.StringBuilder append(char[]);
public java.lang.StringBuilder append(char[], int, int);
public java.lang.StringBuilder append(boolean);
public java.lang.StringBuilder append(char);
public java.lang.StringBuilder append(int);
public java.lang.StringBuilder append(long);
public java.lang.StringBuilder append(float);
public java.lang.StringBuilder append(double);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#4B7FCE</color>
<color name="primary_dark">#4B7FCE</color>
<color name="primary_light">#7BAFCE</color>
<color name="accent">#4B7FCE</color>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloWorld Sample</string>
</resources>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:colorPrimary">@color/primary</item>
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<item name="android:colorAccent">@color/accent</item>
</style>
</resources>

View File

@ -0,0 +1,29 @@
/*
* Sample application to illustrate processing with ProGuard.
*
* Copyright (c) 2012-2020 Guardsquare NV
*/
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TextView;
/**
* Sample activity that displays "Hello world!".
*/
public class HelloWorldActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Display the message.
TextView view = new TextView(this);
view.setText("Hello World");
view.setGravity(Gravity.CENTER);
setContentView(view);
}
}

View File

@ -0,0 +1,17 @@
<?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>

View File

@ -0,0 +1,73 @@
// This build file illustrates how to apply ProGuard in the Android build
// process, with ProGuard's own plugin instead of the built-in minification
// support of the Android Gradle plugin.
buildscript {
repositories {
mavenLocal() // For local testing
google() // For the Android Gradle plugin.
mavenCentral() // For the ProGuard Gradle Plugin and anything else.
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.0.0'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.guardsquare.proguard'
repositories {
google() // For the Android plugin.
mavenCentral() // For anything else.
}
android {
compileSdkVersion 28
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
defaultConfig {
minSdkVersion 11
targetSdkVersion 29
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 {
// Disable the built-in minification
minifyEnabled false
}
release {
// Disable the built-in minification
minifyEnabled false
}
}
}
proguard {
configurations {
release {
defaultConfiguration 'proguard-android-optimize.txt'
configuration 'proguard-project.txt'
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

188
proguard/examples/android-plugin/gradlew vendored Normal file
View File

@ -0,0 +1,188 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@ -0,0 +1,100 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,127 @@
###############################################################################
# General settings.
###############################################################################
-verbose
# We can debug the ProGuard configuration by instrumenting the code and
# checking the log for feedback. Disable the option again for actual releases!
#-addconfigurationdebugging
# We can also disable the individual processing steps.
#-dontshrink
#-dontoptimize
#-dontobfuscate
# Specifically target Android.
-android
###############################################################################
# Settings to handle reflection in the code.
###############################################################################
# Preserve annotated and generated classes for Dagger.
-keepclassmembers,allowobfuscation class * {
@dagger.** *;
}
-keep class **$$ModuleAdapter
-keep class **$$InjectAdapter
-keep class **$$StaticInjection
-if class **$$ModuleAdapter
-keep class <1>
-if class **$$InjectAdapter
-keep class <1>
-if class **$$StaticInjection
-keep class <1>
-keepnames class dagger.Lazy
# Preserve annotated and generated classes for Butterknife.
-keep class **$$ViewBinder {
public static void bind(...);
public static void unbind(...);
}
-if class **$$ViewBinder
-keep class <1>
-keep class **_ViewBinding {
<init>(<1>, android.view.View);
}
-if class **_ViewBinding
-keep class <1>
# Preserve fields that are serialized with GSON.
#-keepclassmembers class com.example.SerializedClass1,
# com.example.SerializedClass2 {
# <fields>;
#}
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
-keep,allowobfuscation @interface com.google.gson.annotations.**
###############################################################################
# Further optimizations.
###############################################################################
# If you wish, you can let the optimization step remove Android logging calls.
#-assumenosideeffects class android.util.Log {
# public static boolean isLoggable(java.lang.String, int);
# public static int v(...);
# public static int i(...);
# public static int w(...);
# public static int d(...);
# public static int e(...);
#}
# In that case, it's especially useful to also clean up any corresponding
# string concatenation calls.
-assumenoexternalsideeffects class java.lang.StringBuilder {
public java.lang.StringBuilder();
public java.lang.StringBuilder(int);
public java.lang.StringBuilder(java.lang.String);
public java.lang.StringBuilder append(java.lang.Object);
public java.lang.StringBuilder append(java.lang.String);
public java.lang.StringBuilder append(java.lang.StringBuffer);
public java.lang.StringBuilder append(char[]);
public java.lang.StringBuilder append(char[], int, int);
public java.lang.StringBuilder append(boolean);
public java.lang.StringBuilder append(char);
public java.lang.StringBuilder append(int);
public java.lang.StringBuilder append(long);
public java.lang.StringBuilder append(float);
public java.lang.StringBuilder append(double);
public java.lang.String toString();
}
-assumenoexternalreturnvalues class java.lang.StringBuilder {
public java.lang.StringBuilder append(java.lang.Object);
public java.lang.StringBuilder append(java.lang.String);
public java.lang.StringBuilder append(java.lang.StringBuffer);
public java.lang.StringBuilder append(char[]);
public java.lang.StringBuilder append(char[], int, int);
public java.lang.StringBuilder append(boolean);
public java.lang.StringBuilder append(char);
public java.lang.StringBuilder append(int);
public java.lang.StringBuilder append(long);
public java.lang.StringBuilder append(float);
public java.lang.StringBuilder append(double);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#4B7FCE</color>
<color name="primary_dark">#4B7FCE</color>
<color name="primary_light">#7BAFCE</color>
<color name="accent">#4B7FCE</color>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloWorld Sample</string>
</resources>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:colorPrimary">@color/primary</item>
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<item name="android:colorAccent">@color/accent</item>
</style>
</resources>

View File

@ -0,0 +1,29 @@
/*
* Sample application to illustrate processing with ProGuard.
*
* Copyright (c) 2012-2020 Guardsquare NV
*/
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TextView;
/**
* Sample activity that displays "Hello world!".
*/
public class HelloWorldActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Display the message.
TextView view = new TextView(this);
view.setText("Hello World");
view.setGravity(Gravity.CENTER);
setContentView(view);
}
}

View File

@ -0,0 +1,65 @@
#
# This ProGuard configuration file illustrates how to use annotations for
# specifying which classes and class members should be kept.
# Usage:
# java -jar proguard.jar @examples.pro
#
# Specify the input, output, and library jars.
# This is assuming the code has been compiled in the examples directory.
-injars examples(*.class)
-outjars out
# Before Java 9, the runtime classes were packaged in a single jar file.
#-libraryjars <java.home>/lib/rt.jar
# As of Java 9, the runtime classes are packaged in modular jmod files.
-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
#-libraryjars <java.home>/jmods/.....
# Some important configuration is based on the annotations in the code.
# We have to specify what the annotations mean to ProGuard.
-include lib/annotations.pro
#
# We can then still add any other options that might be useful.
#
# Print out a list of what we're preserving.
-printseeds
# Preserve all annotations themselves.
-keepattributes *Annotation*
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
# Preserve the special static methods that are required in all enumeration
# classes.
-keepclassmembers,allowoptimization enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# You can comment this out if your application doesn't use serialization.
# If your code contains serializable classes that have to be backward
# compatible, please refer to the manual.
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}

View File

@ -0,0 +1,23 @@
import proguard.annotation.*;
/**
* This applet illustrates the use of annotations for configuring ProGuard.
*
* You can compile it with:
* javac -classpath ../lib/annotations.jar Applet.java
* You can then process it with:
* java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its essential methods,
* as a result of the specifications in lib/annotations.pro.
*/
@Keep
public class Applet extends java.applet.Applet
{
// Implementations for Applet.
public void init()
{
// ...
}
}

View File

@ -0,0 +1,21 @@
import proguard.annotation.KeepApplication;
/**
* This application illustrates the use of annotations for configuring ProGuard.
*
* You can compile it with:
* javac -classpath ../lib/annotations.jar Application.java
* You can then process it with:
* java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its main method,
* as a result of the specifications in lib/annotations.pro.
*/
@KeepApplication
public class Application
{
public static void main(String[] args)
{
System.out.println("The answer is 42");
}
}

View File

@ -0,0 +1,57 @@
import proguard.annotation.*;
/**
* This bean illustrates the use of annotations for configuring ProGuard.
*
* You can compile it with:
* javac -classpath ../lib/annotations.jar Bean.java
* You can then process it with:
* java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotations will preserve the class and its public getters and setters,
* as a result of the specifications in lib/annotations.pro.
*/
@Keep
@KeepPublicGettersSetters
public class Bean
{
public boolean booleanProperty;
public int intProperty;
public String stringProperty;
public boolean isBooleanProperty()
{
return booleanProperty;
}
public void setBooleanProperty(boolean booleanProperty)
{
this.booleanProperty = booleanProperty;
}
public int getIntProperty()
{
return intProperty;
}
public void setIntProperty(int intProperty)
{
this.intProperty = intProperty;
}
public String getStringProperty()
{
return stringProperty;
}
public void setStringProperty(String stringProperty)
{
this.stringProperty = stringProperty;
}
}

View File

@ -0,0 +1,52 @@
import proguard.annotation.*;
/**
* This application illustrates the use of annotations for configuring ProGuard.
*
* You can compile it with:
* javac -classpath ../lib/annotations.jar NativeCallBack.java
* You can then process it with:
* java -jar ../../../lib/proguard.jar @ ../examples.pro
*
* The annotation will preserve the class and its main method,
* as a result of the specifications in lib/annotations.pro.
*/
@KeepApplication
public class NativeCallBack
{
/**
* Suppose this is a native method that computes an answer.
*
* The -keep option for native methods in the regular ProGuard
* configuration will make sure it is not removed or renamed when
* processing this code.
*/
public native int computeAnswer();
/**
* Suppose this method is called back from the above native method.
*
* ProGuard would remove it, because it is not referenced from java.
* The annotation will make sure it is preserved anyhow.
*/
@Keep
public int getAnswer()
{
return 42;
}
/**
* The main entry point of the application.
*
* The @KeepApplication annotation of this class will make sure it is not
* removed or renamed when processing this code.
*/
public static void main(String[] args)
{
int answer = new NativeCallBack().computeAnswer();
System.out.println("The answer is " + answer);
}
}

View File

@ -0,0 +1,89 @@
<!-- This Ant build file illustrates how to process applets.
Usage: ant -f applets.xml -->
<project name="Applets" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
printseeds="on"
printmapping="out.map"
renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="in.jar" />
<outjar file="out.jar" />
<libraryjar file="${java.home}/lib/rt.jar" />
<!-- Optionally preserve line numbers in the obfuscated stack traces.
<keepattribute name="LineNumberTable">
<keepattribute name="SourceFile">
-->
<!-- Preserve all annotations. -->
<keepattribute name="*Annotation*" />
<!-- Preserve all public applets. -->
<keep access="public" extends="java.applet.Applet" />
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames includedescriptorclasses="true">
<method access="native" />
</keepclasseswithmembernames>
<!-- Preserve the methods that are required in all enumeration classes. -->
<keepclassmembers allowoptimization="true" type="enum">
<method access="public static"
type="**[]"
name="values"
parameters="" />
<method access="public static"
type="**"
name="valueOf"
parameters="java.lang.String" />
</keepclassmembers>
<!-- Explicitly preserve all serialization members. The Serializable
interface is only a marker interface, so it wouldn't save them.
You can comment this out if your library doesn't use serialization.
If your code contains serializable classes that have to be backward
compatible, please refer to the manual. -->
<keepclassmembers implements="java.io.Serializable">
<field access ="static final"
type ="long"
name ="serialVersionUID" />
<field access ="static final"
type ="java.io.ObjectStreamField[]"
name ="serialPersistentFields" />
<method access ="private"
type ="void"
name ="writeObject"
parameters="java.io.ObjectOutputStream" />
<method access ="private"
type ="void"
name ="readObject"
parameters="java.io.ObjectInputStream" />
<method type ="java.lang.Object"
name ="writeReplace"
parameters="" />
<method type ="java.lang.Object"
name ="readResolve"
parameters="" />
</keepclassmembers>
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,15 @@
<!-- This Ant build file illustrates how to process applications,
by including a ProGuard-style configuration file.
Usage: ant -f applications1.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard configuration="examples/applications.pro" />
</target>
</project>

View File

@ -0,0 +1,76 @@
<!-- This Ant build file illustrates how to process applications,
by including ProGuard-style configuration options.
Usage: ant -f applications2.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard>
-verbose
<!-- Specify the input jars, output jars, and library jars. -->
-injars in.jar
-outjars out.jar
-libraryjars ${java.home}/lib/rt.jar
<!-- -libraryjars junit.jar -->
<!-- -libraryjars servlet.jar -->
<!-- -libraryjars jai_core.jar -->
<!-- ... -->
<!-- Save the obfuscation mapping to a file, and preserve line numbers. -->
-printmapping out.map
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
<!-- Preserve all annotations. -->
-keepattributes *Annotation*
<!-- Preserve all public applications. -->
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
<!-- Preserve all native method names and the names of their classes. -->
-keepclasseswithmembernames class * {
native &lt;methods&gt;;
}
<!-- Preserve the methods that are required in all enumeration classes. -->
-keepclassmembers,allowoptimization enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
<!-- Explicitly preserve all serialization members. The Serializable
interface is only a marker interface, so it wouldn't save them.
You can comment this out if your library doesn't use serialization.
If your code contains serializable classes that have to be backward
compatible, please refer to the manual. -->
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,99 @@
<!-- This Ant build file illustrates how to process applications,
using a full-blown XML configuration.
Usage: ant -f applications3.xml -->
<project name="Applications" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
printseeds="on"
printmapping="out.map"
renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="in.jar" />
<outjar file="out.jar" />
<libraryjar file="${java.home}/lib/rt.jar" />
<!-- libraryjar file="junit.jar" / -->
<!-- libraryjar file="servlet.jar" / -->
<!-- libraryjar file="jai_core.jar" / -->
<!-- ... / -->
<!-- Preserve line numbers in the obfuscated stack traces. -->
<keepattribute name="LineNumberTable" />
<keepattribute name="SourceFile" />
<!-- Preserve all annotations. -->
<keepattribute name="*Annotation*" />
<!-- Preserve all public applications. -->
<keepclasseswithmembers access="public">
<method access ="public static"
type ="void"
name ="main"
parameters="java.lang.String[]" />
</keepclasseswithmembers>
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames includedescriptorclasses="true">
<method access="native" />
</keepclasseswithmembernames>
<!-- Preserve the methods that are required in all enumeration classes. -->
<keepclassmembers allowoptimization="true" type="enum">
<method access="public static"
type="**[]"
name="values"
parameters="" />
<method access="public static"
type="**"
name="valueOf"
parameters="java.lang.String" />
</keepclassmembers>
<!-- Explicitly preserve all serialization members. The Serializable
interface is only a marker interface, so it wouldn't save them.
You can comment this out if your library doesn't use serialization.
If your code contains serializable classes that have to be backward
compatible, please refer to the manual. -->
<keepclassmembers implements="java.io.Serializable">
<field access ="static final"
type ="long"
name ="serialVersionUID" />
<field access ="static final"
type ="java.io.ObjectStreamField[]"
name ="serialPersistentFields" />
<method access ="private"
type ="void"
name ="writeObject"
parameters="java.io.ObjectOutputStream" />
<method access ="private"
type ="void"
name ="readObject"
parameters="java.io.ObjectInputStream" />
<method type ="java.lang.Object"
name ="writeReplace"
parameters="" />
<method type ="java.lang.Object"
name ="readResolve"
parameters="" />
</keepclassmembers>
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,106 @@
<!-- This Ant build file illustrates how to process a program library,
such that it remains usable as a library.
Usage: ant -f library.xml -->
<project name="Library" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
printmapping="out.map"
renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="library.jar" />
<outjar file="library_out.jar" />
<libraryjar file="${java.home}/lib/rt.jar" />
<!-- Keep some useful attributes. -->
<keepattribute name="Signature" />
<keepattribute name="Exceptions" />
<keepattribute name="InnerClasses" />
<keepattribute name="PermittedSubclasses" />
<keepattribute name="EnclosingMethod" />
<keepattribute name="Deprecated" />
<keepattribute name="SourceFile" />
<keepattribute name="LineNumberTable" />
<!-- Preserve all public classes, and their public and protected fields
and methods. -->
<keep access="public">
<field access="public protected" />
<method access="public protected" />
</keep>
<!-- Preserve all .class method names. -->
<keepclassmembernames access="public">
<method type ="java.lang.Class"
name ="class$"
parameters="java.lang.String" />
<method type ="java.lang.Class"
name ="class$"
parameters="java.lang.String,boolean" />
</keepclassmembernames>
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames includedescriptorclasses="true">
<method access="native" />
</keepclasseswithmembernames>
<!-- Preserve the methods that are required in all enumeration classes. -->
<keepclassmembers allowoptimization="true" type="enum">
<method access="public static"
type="**[]"
name="values"
parameters="" />
<method access="public static"
type="**"
name="valueOf"
parameters="java.lang.String" />
</keepclassmembers>
<!-- Explicitly preserve all serialization members. The Serializable
interface is only a marker interface, so it wouldn't save them.
You can comment this out if your library doesn't use serialization.
If your code contains serializable classes that have to be backward
compatible, please refer to the manual. -->
<keepclassmembers implements="java.io.Serializable">
<field access ="final"
type ="long"
name ="serialVersionUID" />
<field access ="static final"
type ="java.io.ObjectStreamField[]"
name ="serialPersistentFields" />
<method access ="private"
type ="void"
name ="writeObject"
parameters="java.io.ObjectOutputStream" />
<method access ="private"
type ="void"
name ="readObject"
parameters="java.io.ObjectInputStream" />
<method type ="java.lang.Object"
name ="writeReplace"
parameters="" />
<method type ="java.lang.Object"
name ="readResolve"
parameters="" />
</keepclassmembers>
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,53 @@
<!-- This Ant build file illustrates how to process J2ME midlets.
Usage: ant -f midlets.xml -->
<project name="Midlets" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
microedition="on"
printseeds="on"
printmapping="out.map"
overloadaggressively="on"
repackageclasses=""
allowaccessmodification="on"
renamesourcefileattribute="SourceFile">
<!-- On Windows, you can't use mixed case class names,
should you still want to use the preverify tool.
usemixedcaseclassnames="false">
-->
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="in.jar" />
<outjar file="out.jar" />
<libraryjar file="/usr/local/java/wtk2.5.2/lib/midpapi20.jar" />
<libraryjar file="/usr/local/java/wtk2.5.2/lib/cldcapi11.jar" />
<!-- Optionally preserve line numbers in the obfuscated stack traces.
<keepattribute name="LineNumberTable">
<keepattribute name="SourceFile">
-->
<!-- Preserve all public midlets. -->
<keep access="public" extends="javax.microedition.midlet.MIDlet" />
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames includedescriptorclasses="true">
<method access="native" />
</keepclasseswithmembernames>
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,109 @@
<!-- This Ant build file illustrates how to process ProGuard (including its
main application, its GUI, its Ant task, and its WTK plugin), and the
ReTrace tool, all in one go.
Usage: ant -f proguard.xml -->
<project name="ProGuard" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
printmapping="proguard.map"
overloadaggressively="on"
repackageclasses=""
renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="lib/proguard.jar" />
<outjar file="examples/ant/proguard_out.jar" />
<!-- Before Java 9, the runtime classes were packaged in a single jar file. -->
<!-- libraryjar file="${java.home}/lib/rt.jar" -->
<!-- As of Java 9, the runtime classes are packaged in modular jmod files. -->
<libraryjar file="${java.home}/jmods/java.base.jmod" jarfilter="!**.jar" filter="!module-info.class" />
<libraryjar file="${java.home}/jmods/java.sql.jmod" jarfilter="!**.jar" filter="!module-info.class" />
<libraryjar file="${user.home}/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.31/11289d20fd95ae219333f3456072be9f081c30cc/kotlin-stdlib-1.3.31.jar" />
<libraryjar file="${user.home}/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.31/20c34a04ea25cb1ef0139598bd67c764562cb170/kotlin-stdlib-common-1.3.31.jar" />
<libraryjar file="${user.home}/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-metadata-jvm/0.1.0/505481587ce23e1d8207734e496632df5c4e6f58/kotlinx-metadata-jvm-0.1.0.jar" />
<libraryjar file="${user.home}/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.8.5/f645ed69d595b24d4cf8b3fbb64cc505bede8829/gson-2.8.5.jar" />
<!-- Don't print notes about reflection in GSON code, the Kotlin runtime, and our own optionally injected code. -->
<dontnote filter="kotlin.**" />
<dontnote filter="kotlinx.**" />
<dontnote filter="com.google.gson.**" />
<dontnote filter="proguard.configuration.ConfigurationLogger" />
<!-- Preserve injected GSON utility classes and their members. -->
<keep name="proguard.optimize.gson._*" allowobfuscation="true" />
<keepclassmembers name="proguard.optimize.gson._*">
<field name="*" />
<method name="*" />
</keepclassmembers>
<!-- Obfuscate class strings of injected GSON utility classes. -->
<adaptclassstrings name="proguard.optimize.gson.**" />
<!-- Adapt the resource file names, based on the corresponding obfuscated
class names. -->
<adaptresourcefilenames filter="**.properties,**.gif,**.jpg" />
<adaptresourcefilecontents filter="proguard/ant/task.properties" />
<!-- Optionally preserve line numbers in the obfuscated stack traces.
<keepattribute name="LineNumberTable">
<keepattribute name="SourceFile">
-->
<!-- The main seeds: ProGuard and its companion tool ReTrace. -->
<keep access="public" name="proguard.ProGuard">
<method access ="public static"
type ="void"
name ="main"
parameters="java.lang.String[]" />
</keep>
<keep access="public" name="proguard.gui.ProGuardGUI">
<method access ="public static"
type ="void"
name ="main"
parameters="java.lang.String[]" />
</keep>
<keep access="public" name="proguard.retrace.ReTrace">
<method access ="public static"
type ="void"
name ="main"
parameters="java.lang.String[]" />
</keep>
<!-- If we have ant.jar, we can properly process the Ant task. -->
<keeppackagename name="proguard.ant" />
<keep name="proguard.ant.*" allowobfuscation="true" />
<keepclassmembers access="public" name="proguard.ant.*">
<constructor parameters="org.apache.tools.ant.Project" />
<method access="public" type="void" name="set*" parameters="***" />
<method access="public" type="void" name="add*" parameters="***" />
</keepclassmembers>
<!-- If we have the Gradle jars, we can properly process the Gradle task. -->
<keep access="public" name="proguard.gradle.*">
<method access="public" />
</keep>
<!-- If we have kenv.zip, we can process the J2ME WTK plugin. -->
<keep access="public" name="proguard.wtk.ProGuardObfuscator" />
</proguard>
</target>
</project>

View File

@ -0,0 +1,89 @@
<!-- This Ant build file illustrates how to process servlets.
Usage: ant -f servlets.xml -->
<project name="Servlets" default="obfuscate" basedir="../..">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="lib/proguard.jar" />
<proguard verbose="true"
printseeds="on"
printmapping="proguard.map"
renamesourcefileattribute="SourceFile">
<!-- Specify the input jars, output jars, and library jars. -->
<injar file="in.jar" />
<outjar file="out.jar" />
<libraryjar file="${java.home}/lib/rt.jar" />
<!-- Optionally preserve line numbers in the obfuscated stack traces.
<keepattribute name="LineNumberTable">
<keepattribute name="SourceFile">
-->
<!-- Preserve all annotations. -->
<keepattribute name="*Annotation*" />
<!-- Keep all public servlets. -->
<keep access="public" implements="javax.servlet.Servlet" />
<!-- Preserve all native method names and the names of their classes. -->
<keepclasseswithmembernames includedescriptorclasses="true">
<method access="native" />
</keepclasseswithmembernames>
<!-- Preserve the methods that are required in all enumeration classes. -->
<keepclassmembers allowoptimization="true" type="enum">
<method access="public static"
type="**[]"
name="values"
parameters="" />
<method access="public static"
type="**"
name="valueOf"
parameters="java.lang.String" />
</keepclassmembers>
<!-- Explicitly preserve all serialization members. The Serializable
interface is only a marker interface, so it wouldn't save them.
You can comment this out if your library doesn't use serialization.
If your code contains serializable classes that have to be backward
compatible, please refer to the manual. -->
<keepclassmembers implements="java.io.Serializable">
<field access ="static final"
type ="long"
name ="serialVersionUID" />
<field access ="static final"
type ="java.io.ObjectStreamField[]"
name ="serialPersistentFields" />
<method access ="private"
type ="void"
name ="writeObject"
parameters="java.io.ObjectOutputStream" />
<method access ="private"
type ="void"
name ="readObject"
parameters="java.io.ObjectInputStream" />
<method type ="java.lang.Object"
name ="writeReplace"
parameters="" />
<method type ="java.lang.Object"
name ="readResolve"
parameters="" />
</keepclassmembers>
<!-- Your application may contain more items that need to be preserved;
typically classes that are dynamically created using Class.forName -->
</proguard>
</target>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$USER_HOME$/.sdkman/candidates/gradle/4.10.2" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ReplaceUntilWithRangeUntil" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.7.21" />
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="beb0481a-9fcb-40ec-a128-e9a0bc35ae01" name="Changes" comment="Add simple Kotlin example application" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="DefaultGradleProjectSettings">
<option name="isMigrated" value="true" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2KGgLM0XNRr9GUCTrjtWmKoLSqY" />
<component name="ProjectViewState">
<option name="autoscrollFromSource" value="true" />
<option name="foldersAlwaysOnTop" value="false" />
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
<option name="showMembers" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"last_opened_file_path": "/home/james/Projects/jlox"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
</key>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="beb0481a-9fcb-40ec-a128-e9a0bc35ae01" name="Changes" comment="" />
<created>1673606278294</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1673606278294</updated>
</task>
<task id="LOCAL-00001" summary="Add simple Kotlin example application">
<created>1673610276662</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1673610276662</updated>
</task>
<option name="localTasksCounter" value="2" />
<servers />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="Add simple Kotlin example application" />
<option name="LAST_COMMIT_MESSAGE" value="Add simple Kotlin example application" />
</component>
</project>

View File

@ -0,0 +1,69 @@
import proguard.gradle.ProGuardTask
buildscript {
repositories {
mavenLocal()
mavenCentral()
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.3.1'
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.8.0'
id 'application'
}
group = 'org.example'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test'
}
test {
useJUnitPlatform()
}
compileKotlin {
kotlinOptions.jvmTarget = '1.8'
}
compileTestKotlin {
kotlinOptions.jvmTarget = '1.8'
}
application {
mainClassName = 'AppKt'
}
ext.baseCoordinates = "${project.name}-${project.version}"
tasks.register('proguard', ProGuardTask) {
configuration file('proguard.pro')
injars(tasks.named('jar', Jar).flatMap { it.archiveFile })
// Automatically handle the Java version of this build.
if (System.getProperty('java.version').startsWith('1.')) {
// Before Java 9, the runtime classes were packaged in a single jar file.
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
} else {
// As of Java 9, the runtime classes are packaged in modular jmod files.
libraryjars "${System.getProperty('java.home')}/jmods/java.base.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
//libraryjars "${System.getProperty('java.home')}/jmods/....."
}
// This will include the Kotlin library jars
libraryjars sourceSets.main.compileClasspath
verbose
outjars(layout.buildDirectory.file("libs/${baseCoordinates}-minified.jar"))
}

View File

@ -0,0 +1 @@
kotlin.code.style=official

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,8 @@
-verbose
-keepattributes *Annotation*
-keep class kotlin.Metadata { *; }
# Entry point to the app.
-keep class com.example.AppKt { *; }

View File

@ -0,0 +1,3 @@
rootProject.name = 'application-kotlin'

View File

@ -0,0 +1,9 @@
package com.example
fun main(args: Array<String>) {
println("Hello World!")
// Try adding program arguments via Run/Debug configuration.
// Learn more about running applications: https://www.jetbrains.com/help/idea/running-applications.html.
println("Program arguments: ${args.joinToString()}")
}

Some files were not shown because too many files have changed in this diff Show More