213 lines
10 KiB
Markdown
213 lines
10 KiB
Markdown
## 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.
|