*.class) to Dalvik
bytecode for Android (classes.dex).
| Input code | ||||||||
| Shrunk code | ||||||||
| Optim. code | ||||||||
| - shrink → | - optimize → | - obfuscate → | Obfusc. code | - convert → | Output code | |||
| Platform libraries | ------------------------------- (unchanged) -------------------------------→ | Platform libraries | ||||||
DexGuard first reads the input code (jars, aars, wars, ears, zips, apks, or directories, containing Java class files). The input code includes any library projects and third-party libraries. DexGuard then subsequently shrinks, optimizes, obfuscates, and converts the code. You can optionally let DexGuard perform multiple optimization passes. DexGuard packages the processed output code in output archives (jars, aars, wars, ears, zips, apks, or directories, containing Dalvik bytecode). DexGuard can optionally sign and align these archives, removing the need for external tools. The input may contain resource files, whose names and contents can optionally be updated to reflect the obfuscated class names.
DexGuard requires the platform libraries (jars, aars, wars, ears, zips,
apks, or directories) to properly process the code. For the standard Android
platform, this is simply android.jar.
The Ant build process and the Eclipse build process of DexGuard automatically
set the proper input and the proper libraries for you. You only need to
consider them if you create your own build process.
The Usage section of this manual describes the
necessary -keep options and
the Examples section provides plenty of examples.
The Ant build process and the Eclipse build process of DexGuard automatically
set the most common entry points for you. You only need to consider them if
you create your own build process, or if your code uses reflection, as
discussed below.
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 DexGuard configuration, with the same
simple -keep options.
However, DexGuard will already detect and handle the following cases for you:
Class.forName("SomeClass")SomeClass.classSomeClass.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")
Furthermore, DexGuard will offer some suggestions if keeping some classes or
class members appears necessary. For example, DexGuard 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.
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.