DOCUMENTATION

Documentation

1 Configuration file structure
   1.1 Input tag
   1.2 Classpath tag
   1.3 Keep-names tag
      1.3.1 class tag
      1.3.2 field tag
      1.3.3 method tag
   1.4 Watermark tag
   1.5 Expiry tag
   1.6 Property tag
      1.6.1 General properties
         1.6.1.1 log-file
         1.6.1.2 random-seed
      1.6.2 String encryption properties
         1.6.2.1 string-encryption
         1.6.2.2 string-encryption-type
         1.6.2.3 string-encryption-version
         1.6.2.4 string-encryption-ignored-strings
      1.6.3 Control flow obfuscation properties
         1.6.3.1 control-flow-obfuscation
         1.6.3.2 extensive-flow-obfuscation
      1.6.4 Renaming properties
         1.6.4.1 default-package
         1.6.4.2 force-default-package
         1.6.4.3 packages-naming
         1.6.4.4 classes-naming
         1.6.4.5 methods-naming
         1.6.4.6 fields-naming
         1.6.4.7 classes-naming-prefix
         1.6.4.8 methods-naming-prefix
         1.6.4.9 fields-naming-prefix
         1.6.4.10 local-variables-naming
         1.6.4.11 skip-renaming
         1.6.4.12 update-resource-names
         1.6.4.13 update-resource-contents
      1.6.5 Other properties
         1.6.5.1 line-numbers
         1.6.5.2 generics
         1.6.5.3 inner-classes
         1.6.5.4 throws-clause
         1.6.5.5 member-reorder
         1.6.5.6 finalize
         1.6.5.7 version-marker
         1.6.5.8 synthetize-methods
         1.6.5.9 synthetize-fields
         1.6.5.10 set-methods-to-public
         1.6.5.11 set-fields-to-public
         1.6.5.12 remove-toString
         1.6.5.13 remove-calls
         1.6.5.14 remove-annotations
         1.6.5.15 output-jar-compression-level
         1.6.5.16 output-jar-duplicate-name-entries
      1.6.6 Incremental obfuscation properties
         1.6.6.1 incremental-obfuscation
         1.6.6.2 unique-renaming
   1.7 Ignore-classes tag
2 Annotations
3 Android obfuscation
   3.1 Using Android Studio
   3.2 Using Ant
4 Eclipse IDE plugin

1 Configuration file structure

Allatori configuration file is a XML file with the following structure:

<config>
    <input basedir="input-jars" single-jar="application.jar">
        <jar in="app.jar" out="app-obf.jar"/>
        <jar in="input/*.jar" out="output/*.jar"/>

        <dir in="in-dir" out="out-dir"/>
    </input>

    <classpath basedir="library-jars">
        
<!-- Adding library.jar to the classpath -->
<jar name="library.jar"/>
<!-- Adding all jars in the lib directory to the classpath -->
<jar name="lib/*.jar"/>
<!-- Adding all jars in the lib2 directory and its subdirectories to the classpath -->
<jar name="lib2/**/*.jar"/> </classpath> <keep-names> <class template="class SomeClass"/> <class template="class * instanceof java.io.Serializable"/> <class template="class com.package.*"/> <class access="protected+"> <field access="protected+"/> <method access="protected+"/> </class> <class template="class com.company.abc.*"> <field template="public int *"/> <method template="public get*(*)"/> <method template="public set*(*)"/> </class> </keep-names> <watermark key="secure-key-to-extract-watermark" value="Customer: John Smith"/> <expiry date="2017/01/01" string="EXPIRED!"/>
<!-- Configuration properties, all properties are optional -->
<!-- General properties, we recommend to use these two properties -->
<property name="log-file" value="renaming-log.xml"/> <property name="random-seed" value="type anything here"/>
<!-- String encryption -->
<property name="string-encryption" value="enable"/> <property name="string-encryption-type" value="fast"/> <property name="string-encryption-version" value="v4"/> <property name="string-encryption-ignored-strings" value="patterns.txt"/>
<!-- Control flow obfuscation -->
<property name="control-flow-obfuscation" value="enable"/> <property name="extensive-flow-obfuscation" value="normal"/>
<!-- Renaming -->
<property name="default-package" value="com.package"/> <property name="force-default-package" value="enable"/> <property name="packages-naming" value="abc"/> <property name="classes-naming" value="compact"/> <property name="methods-naming" value="compact"/> <property name="fields-naming" value="compact"/> <property name="local-variables-naming" value="optimize"/> <property name="update-resource-names" value="enable"/> <property name="update-resource-contents" value="enable"/>
<!-- Other -->
<property name="line-numbers" value="obfuscate"/> <property name="generics" value="remove"/> <property name="inner-classes" value="remove"/> <property name="throws-clause" value="remove"/> <property name="member-reorder" value="random"/> <property name="finalize" value="disable"/> <property name="version-marker" value="anyValidIdentifierName"/> <property name="synthetize-methods" value="all"/> <property name="synthetize-fields" value="all"/> <property name="remove-toString" value="enable"/> <property name="remove-calls" value="com.package.Logger.debug"/> <property name="output-jar-compression-level" value="9"/>
<!-- Incremental obfuscation -->
<property name="incremental-obfuscation" value="input-renaming-log.xml"/> </config>

Note 1. All relative paths are resolved against configuration file location.
Note 2. If you run Allatori from Ant, then you can reference properties defined in the Ant build file using standard Ant syntax: ${PropertyName}.
Note 3. System properties and environment variables could be referenced using ${System.getProperty(property.name)} and ${System.getenv(VARIABLE_NAME)} respectively.


1.1 Input tag

The input tag is used to set jar (war, ear) files that should be obfuscated. It should contain at least one nested jar or dir tag to set input and output files.

The input tag has two optional attributes:

Attribute Value
basedir Optional. Relative paths to jar files will be resolved against the specified directory. By default, relative paths are resolved against configuration file location.
single-jar Optional. Allatori will create an additional output jar file with all obfuscated classes.


The nested jar tag has two required attributes:

Attribute Value
in Required. The name of the jar file to obfuscate.
out Required. The name of the output jar file. It can be the same as in, in such case the jar will be overwritten with its obfuscated version.


The nested dir tag has two required attributes:

Attribute Value
in Required. The name of the directory with class files to obfuscate.
out Required. The name of the output directory for obfuscated class files. The output directory will not be emptied before writing new files to avoid accidental removal of data in the case of typo in the config. You should empty the output directory before running Allatori (i.e. using Ant's delete task).

Example:

    <input basedir="input-jars" single-jar="application.jar">
        <jar in="app.jar" out="app-obf.jar"/>
        <jar in="input/*.jar" out="output/*.jar"/>

        <dir in="in-dir" out="out-dir"/>
    </input>


1.2 Classpath tag

The classpath tag is used to set the classpath for the obfuscated application. It contains nested jar tags with the names of jar files. It is not necessary to reference all library jars needed by your application, but missing classpath elements may result in a weaker obfuscation. Allatori will warn you about all missing classes during the obfuscation process.

The classpath tag has one optional attribute:

Attribute Value
basedir Optional. Relative paths to jar files will be resolved against the specified directory. By default, relative paths are resolved against configuration file location.


The nested jar tag has one required attribute:

Attribute Value
name Required. The name of jar file to add to the classpath. Wildcard syntax is allowed: "*" matches any characters in the file name; "**" recurses into subdirectories.

Example:

    <classpath basedir="library-jars">
        
<!-- Adding library.jar to the classpath -->
<jar name="library.jar"/>
<!-- Adding all jars in the lib directory to the classpath -->
<jar name="lib/*.jar"/>
<!-- Adding all jars in the lib2 directory and its subdirectories to the classpath -->
<jar name="lib2/**/*.jar"/> </classpath>


1.3 Keep-names tag

The keep-names tag is used to set names of classes, methods and fields that should not be renamed during the obfuscation process. If the obfuscated application is a library, then you should keep all public API. For stand-alone applications, you should keep at least the main class's name. You should also keep names of classes and methods which are used via reflection.

You can use
annotations for more accurate control of renamed elements. Annotations override configuration file settings.

The keep-names tag contains any number of the following nested tags:
    field tag to specify fields that should not be renamed;
    method tag to specify methods that should not be renamed;
    class tag to specify classes that should not be renamed. Can, in turn, contain nested field and method tags.

These nested tags set rules for matching names of classes, fields and methods. Matched names will not be renamed. All these tags can have either access or template attribute.

The access attribute matches elements by access levels and can have the following values:

Value Description
private Matches classes, fields or methods with private access.
private+ Matches classes, fields or methods with private or wider access.
package Matches classes, fields or methods with package access.
package+ Matches classes, fields or methods with package or wider access.
protected Matches classes, fields or methods with protected access.
protected+ Matches classes, fields or methods with protected or wider access.
public Matches classes, fields or methods with public access.


The template attribute is similar to Java language syntax. It has different formats for class, field and method tags.


The class tag is used to match classes. It has the following attributes:

Attribute Value
access Required*. Sets matching rule. Possible values are above.
template Required*. Sets matching rule. Its format is described below.
ignore Optional.
If set to "true" or "yes", then matched classes will be renamed, but nested method and field tags will be processed as usual. It allows to keep names of some fields and methods without keeping the name of the class.

If set to "keep-if-members-match", then at least one of the nested method or field tags should also match to keep class name.
stop Optional. If set to "true" or "yes", then Allatori will stop applying any further rules to the matched classes.
 * Either access or template attribute is required.

template attribute of the class tag has the following format:

[@annotation] [modifiers] (class | interface) classname [extends classname]
                                                        [implements classname]
                                                        [instanceof classname]

The '*' symbol in class or type name matches any number of characters. If name starts with 'regex:', then it is treated like a standard regular expression.

Examples:

Value Description
class * Matches all classes and interfaces.
interface * Matches all interfaces.
public class * Matches all public classes and interfaces.
protected+ class * Matches all protected and public classes and interfaces.
class *abc* Matches all classes containing "abc" in their fully qualified name.
class com.abc.* Matches all classes in the com.abc package and its subpackages.
class *.abc.* Matches all classes in all "abc" packages and their subpackages.
class * extends java.util.Enumeration Matches all classes extending java.util.Enumeration.
class * extends *.Enumeration Matches all classes extending Enumeration.
class * instanceof java.io.Serializable Matches all classes that are instances of java.io.Serializable.
class * implements *.MouseListener Matches all classes implementing MouseListener.
@java.lang.Deprecated class * Matches all deprecated classes.
class regex:com.package.(foo|bar).* Matches all classes in com.package.foo and com.package.bar packages and their subpackages.
class regex:com\.package\.(foo|bar)\..* More precise version of the above rule. Dots should be escaped, as unescaped dot now means any character.


The field tag is used to match fields. If field tag is nested in the class tag, then it is applied only to classes matched by the parent class tag. If parent tag is keep-names, then it is applied to all classes. The field tag has the following attributes:

Attribute Value
access Required*. Sets matching rule. Possible values are above.
template Required*. Sets matching rule. Its format is described below.
 * Either access or template attribute is required.

template attribute of the field tag has the following format:

[@annotation] [modifiers] [type] fieldname [instanceof classname]

The '*' symbol in field or type name matches any number of characters. If name starts with 'regex:', then it is treated like a standard regular expression.

Examples:

Value Description
* Matches all fields.
private * Matches all private fields.
private+ * Matches all fields.
protected+ * Matches all protected and public fields.
static * Matches all static fields.
public static * Matches all public static fields.
public int * Matches all public integer fields.
java.lang.String * Matches all String fields.
java.lang.* * Matches all fields with type in java.lang package.
abc* Matches all fields which names start with "abc".
private abc* Matches all private fields which names start with "abc".
* instanceof java.io.Serializable Matches all serializable fields.
@java.lang.Deprecated * Matches all deprecated fields.
regex:(a|b).* Matches all fields which names start with "a" or "b".


The method tag is used to match methods. If method tag is nested in the class tag, then it is applied only to classes matched by the parent class tag. If parent tag is keep-names, then it is applied to all classes. The method tag has the following attributes:

Attribute Value
access Required*. Sets matching rule. Possible values are above.
template Required*. Sets matching rule. Its format is described below.
parameters Optional. If set to "keep", then names of method's parameters will not be changed. Useful for public API methods.
 * Either access or template attribute is required.

template attribute of the method tag has the following format:

[@annotation] [modifiers] [type] methodname(arguments)

The '*' symbol in method or type name matches any number of characters. The '*' symbol in arguments matches any single argument. Use "**" to match any number of arguments. If name starts with 'regex:', then it is treated like a standard regular expression.

Examples:

Value Description
*(**) Matches all methods.
private *(**) Matches all private methods.
private+ *(**) Matches all methods.
protected+ *(**) Matches all protected and public methods.
private+ *(*) Matches all methods with exactly one argument.
private+ *(*,*) Matches all methods with exactly two arguments.
private+ *(java.lang.String) Matches all methods with exactly one argument of String type.
private+ *(java.lang.String,**) Matches all methods with String as the first argument.
private+ *(java.lang.*) Matches all methods with exactly one argument which type is in java.lang package.
public get*(**) Matches all public methods which names start with "get".
public *abc*(**) Matches all public methods which names contain "abc".
private+ int *(**) Matches all methods with int return type.
@java.lang.Deprecated *(**) Matches all deprecated methods.
public regex:(g|s)et.*(**) Matches all public getter and setter methods.


Example:

    <keep-names>
        
<!-- Stops applying further rules to classes in the com.company.abc package, therefore all classes, methods and fields in this package will be renamed -->
<class template="class com.company.abc.*" stop="true"/>
<!-- Further rules instruct Allatori not to rename matched elements -->
<!-- Matches classes with the name "Main" in any package -->
<class template="class *.Main"/>
<!-- Matches classes with the name ending with "Bean" -->
<class template="class *Bean">
<!-- Matches all fields -->
<field access="private+"/>
<!-- Matches public integer fields -->
<field template="public int *"/>
<!-- Matches all static fields -->
<field template="static *"/>
<!-- Matches protected and public String fields -->
<field template="protected+ java.lang.String *"/>
<!-- Matches all methods -->
<method template="private+ *(**)"/>
<!-- Matches all getter methods -->
<method template="private+ get*(**)"/>
<!-- Matches all methods with String argument, parameter names of these methods will not be changed -->
<method template="private+ *(java.lang.String)" parameters="keep"/> </class>
<!-- Matches serialization members -->
<class template="class * instanceof java.io.Serializable"> <field template="static final long serialVersionUID"/> <method template="void writeObject(java.io.ObjectOutputStream)"/> <method template="void readObject(java.io.ObjectInputStream)"/> <method template="java.lang.Object writeReplace()"/> <method template="java.lang.Object readResolve()"/> </class>
<!-- Matches applets -->
<class template="class * instanceof java.applet.Applet"/>
<!-- Matches servlets -->
<class template="class * instanceof javax.servlet.Servlet"/>
<!-- Matches midlets -->
<class template="class * instanceof javax.microedition.midlet.MIDlet"/> </keep-names>


1.4 Watermark tag

The watermark tag is used to set key and value for watermarking. The tag has two attributes:

Attribute Value
key Required. The key used to embed a watermark into the application using steganography techniques.
value Required for adding watermark. Any string that will be embedded into the application jars. It can be copyright, customer name, company name or any other information that uniquely identifies the build. A watermark can be used to identify owners of the software or track the origin of a pirated copy.

Example:

    <watermark key="secure-key-to-extract-watermark" value="Customer: John Smith"/>

Watermark can also be added without obfuscation to already obfuscated or non-obfuscated jars. Complete examples of adding and extracting watermarks can be found in the tutorial that comes with Allatori distribution.


1.5 Expiry tag

The expiry tag is used to set expiry date to your application. Expiry date checks are inserted into many methods, not just main method, therefore cannot be easily removed. This feature can be used to obfuscate libraries that do not even have main method. The tag has two required attributes:

Attribute Value
date Required. Expiry date in the yyyy/mm/dd format.
string Required. Any string message for the exception thrown if the application is run after the specified expiry date.

Example:

    <expiry date="2017/01/01" string="EXPIRED!"/>

Complete example of using expiry date can be found in the tutorial that comes with Allatori distribution.


1.6 Property tag

The property tag is used to set different obfuscation properties. The tag has two required attributes - name and value:

    <property name="property-name" value="property-value"/>

1.6.1 General properties
1.6.1.1 log-file

Value Description
filename Allatori will write obfuscation log to the specified file. If the property is not set, then log file is not created.
Relative paths are resolved against configuration file location.

The log file is used to restore original stack trace from the obfuscated one. It keeps obfuscated-to-original mapping of names and line numbers.

Examples:

    <property name="log-file" value="log.xml"/>
    <property name="log-file" value="logs/file.xml"/>

Stack trace utility takes log file and restores original names:

    java -cp allatori.jar com.allatori.StackTrace2 log.xml input.txt output.txt


1.6.1.2 random-seed

Value Description
any string String to initialize random number generator.

The default value is current time in milliseconds.

By default, if you run Allatori twice on the same input jars, it will produce different output jars. Renamed classes, fields and methods will have different names, fields and methods will be reordered differently, etc. This is done to make analyzing two versions of the obfuscated application extremely difficult. If you need the same output jars over several consecutive runs of Allatori, then you need to set the random seed. We recommend changing the random seed for different public releases of your application.

Example:

    <property name="random-seed" value="any text here"/>


1.6.2 String encryption properties
1.6.2.1 string-encryption

Value Description
enable (default) All string literals that can be safely changed with the encrypted value will be encrypted. Allatori will add a method to decrypt strings on run-time.
disable String encryption is disabled.
maximum All string literals will be encrypted. See limitations below.
maximum-with-warnings All string literals will be encrypted. Every string comparison using == operator will produce a warning, and you'll be able to replace these comparisons with equals() calls.

Sometimes, strings are compared this way:

    String myString = "Hello";
    ...
    public boolean test() {
        return myString == "Hello";
    }

Although it is a bad practice to compare strings using == operator instead of equals method, the method in the example above will return true, because JVM caches String objects to reuse them within the same class. However, after string encryption the method will look something like this:

public boolean test() {
    return myString == new String("Hello");
    // "Hello" string isn't encrypted to make this example more clear
}

This version of the method will return false, because compared objects are different.

If you set string-encryption property to enable, then Allatori will not encrypt strings which are compared using == operator, and your application will work correctly.

If you are always using equals method to compare strings, then set string-encryption property to maximum.

Example:

    <property name="string-encryption" value="enable"/>

String encryption can be enabled/disabled in the specified classes using annotations or apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Disabling string encryption for classes in com.abc package -->
<property name="string-encryption" value="disable" apply2class="class com.abc.*"/>
<!-- Enabling string encryption for all other classes -->
<property name="string-encryption" value="enable"/>


1.6.2.2 string-encryption-type

Value Description
fast (default) Allatori will use very fast string encryption algorithm.
strong Allatori will use strong and tricky string encryption algorithm. It is, however, slower.
custom
(package.EncryptClassName.encryptMethodName,
package.DecryptClassName.decryptMethodName)
Allatori will use specified string encryption/decryption methods. See below for more information.

String encryption should be enabled for this property to take effect.

Example:

    <property name="string-encryption-type" value="strong"/>

String encryption type can be applied to the specified classes using annotations or apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Setting strong string encryption type for classes in com.abc package -->
<property name="string-encryption-type" value="strong" apply2class="class com.abc.*"/>
<!-- Setting fast string encryption type for all other classes -->
<property name="string-encryption-type" value="fast"/>

Custom string encryption.
Usage samples could be found in the tutorial/step15-custom-string-encryption folder.

Encryption method is needed during obfuscation only, it is not needed in the runtime of your application. It could be located in a separate jar file not included in your distribution. Decryption method is needed in the runtime and could be put in any class of your application.

You can combine custom string encryption with Allatori string encryption

    <property name="string-encryption-type"
value="custom(package.EncryptClassName.encryptMethodName, package.DecryptClassName.decryptMethodName)"
apply2class="class com.some.package.*"/>

and use multiple custom string encryption methods
    <property name="string-encryption-type"
value="custom(EncryptClassName1.encryptMethodName1, DecryptClassName1.decryptMethodName1)"
apply2class="class com.some.package.*"/>
    <property name="string-encryption-type"
value="custom(EncryptClassName2.encryptMethodName2, DecryptClassName2.decryptMethodName2)"
apply2class="class com.some.other.package.*"/>
    
<!-- Methods for classes not matched by the rules above -->
<property name="string-encryption-type" value="custom(EncryptClassName3.encryptMethodName3, DecryptClassName3.decryptMethodName3)"/>

As custom string encryption feature replaces strings in the runtime, it could be used for internationalization instead of encryption. Encryption method would be called for all strings during the obfuscation process (if string encryption is set to maximum), so you can use it to log all strings. And decryption method would replace strings with their internationalized versions in the runtime.



1.6.2.3 string-encryption-version

Value Description
v4 (default) New string encryption algorithm will be used.
v3 Allatori will use string encryption algorithm from the 3.X version.

String encryption should be enabled for this property to take effect.

It doesn't mean that v3 algorithm is outdated. We'll make changes to both v3 and v4 algorithms from time to time to keep them fresh. This property was introduced as the key ideas of v3 and v4 algorithms are very different.

Example:

    <property name="string-encryption-version" value="v3"/>


1.6.2.4 string-encryption-ignored-strings

Value Description
filename Text file containing string literals which should be excluded from obfuscation. These strings will not be encrypted.

The specified text file contains string templates. Each line is a new template, '*' matches any number of any characters. If template line starts with "regex:", then it is processed as a regular expression:

Copyright*
All Rights Reserved*
*CompanyName*
regex:\d+

Example:

    <property name="string-encryption-ignored-strings" value="patterns.txt"/>


1.6.3 Control flow obfuscation properties
1.6.3.1 control-flow-obfuscation

Value Description
enable (default) Allatori will alter the code of the methods. It will not change the application behaviour at run-time, but will make the decompilation process much harder. Generally, control flow obfuscation also makes application smaller and faster.
disable Control flow obfuscation is disabled.

Example:

    <property name="control-flow-obfuscation" value="enable"/>

Control flow obfuscation can be enabled/disabled in the specified classes using annotations or apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Disabling control flow obfuscation for classes in com.abc package -->
<property name="control-flow-obfuscation" value="disable" apply2class="class com.abc.*"/>
<!-- Enabling control flow obfuscation for all other classes -->
<property name="control-flow-obfuscation" value="enable"/>


1.6.3.2 extensive-flow-obfuscation

Value Description
normal (default) Allatori will use control flow obfuscation techniques, which make the obfuscated application a bit bigger and slower. However, Allatori will minimize the number of such code transformations.
disable Extensive control flow obfuscation is disabled.
maximum Allatori will fully use control flow obfuscation techniques, which make the obfuscated application a bit bigger and slower.

Control flow obfuscation should be enabled for this property to take effect.

Example:

    <property name="extensive-flow-obfuscation" value="maximum"/>

Extensive control flow obfuscation can be applied to the specified classes using annotations or apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Using "maximum" value for classes in com.abc package -->
<property name="extensive-flow-obfuscation" value="maximum" apply2class="class com.abc.*"/>
<!-- Using "normal" value for all other classes -->
<property name="extensive-flow-obfuscation" value="normal"/>


1.6.4 Renaming properties
1.6.4.1 default-package

Value Description
package name Full package name, existing or new.

If all classes in some package are renamed, then Allatori will move them to the default package. To move absolutely all renamed classes to the default package, you should enable the force-default-package property. The usage of "" as the default package will reduce the size of the resulting jar.

Examples:

    <property name="default-package" value=""/>
    <property name="default-package" value="com.company.product"/>


1.6.4.2 force-default-package

Value Description
disable (default) Only classes from packages where all classes are renamed will be moved to the default package.
enable Absolutely all renamed classes will be moved to the default package.

Default package should be set for this property to take effect.

Example:

    <property name="force-default-package" value="enable"/>


1.6.4.3 packages-naming

Value Description
abc (default) Packages will be renamed to 'a', 'b', 'c', 'd', ..., 'aa', 'ab', etc. Names will have lower-case letters only.
ABC Packages will be renamed to 'A', 'B', 'C', 'D', ..., 'AA', 'AB', etc. Names will have upper-case letters only.
123 Packages will be renamed to '1', '2', '3', ..., '00', '01', etc.
keep Packages will keep their original names.
custom(filename.txt) Names will be constructed using the provided text file. Each line of the file represents a single name element. If the file has two lines '0' and '1', then the generated names would be '0', '1', '00', '01', '10', '11', '000', etc.

Example:

    <property name="packages-naming" value="abc"/>


1.6.4.4 classes-naming

Value Description
compact (default) Allatori will use single-character names as much as possible, thus making the resulting jar smaller. Classes may have mixed-case names differing only in case (a.class and A.class). Jar files allow mixed-case file names, while Windows file system does not, so it will be tricky to unzip some classes (a.class will overwrite A.class on Windows when unzipped). The jar file with mixed-case file names will work fine on all platforms including Windows.
iii All names will have the same length and differ in case only - iiii, iiiI, iiIi, etc. The resulting jar file will be bigger comparing to other renaming options.
abc Classes will be renamed to 'a', 'b', 'c', 'd', ..., 'aa', 'ab', etc. Names will have lower-case letters only.
ABC Classes will be renamed to 'A', 'B', 'C', 'D', ..., 'AA', 'AB', etc. Names will have upper-case letters only.
123 Classes will be renamed to '1', '2', '3', ..., '00', '01', etc.
windows Allatori will use names prohibited on Windows ('con', 'prn', 'aux', 'nul', etc.) as class names. It is ok to have con.class in the jar, but this class cannot be unzipped on Windows. Classes may also have mixed-case names differing only in case. The jar file with such file names will work fine on all platforms including Windows. This option makes the resulting jar file bigger comparing to compact or abc naming.
custom(filename.txt) Names will be constructed using the provided text file. Each line of the file represents a single name element. If the file has two lines '0' and '1', then the generated names would be '0', '1', '00', '01', '10', '11', '000', etc.
unique All renamed classes will have unique names. There will be no matching class names in different packages. Can be combined with other classes naming options.
keep-$-sign Renamed classes will retain Java inner class naming notation, i.e. classes Foo and Foo$Bar will be renamed to a and a$b. By default, Allatori will rename Foo and Foo$Bar to a and b. Can be combined with other classes naming options.

Example:

    <property name="classes-naming" value="abc"/>


1.6.4.5 methods-naming

Value Description
compact (default) Allatori will use single-character names as much as possible, thus making the resulting jar smaller.
iii All names will have the same length and differ in case only - iiii, iiiI, iiIi, etc. The resulting jar file will be bigger comparing to other renaming options.
abc Methods will be renamed to 'a', 'b', 'c', 'd', ..., 'aa', 'ab', etc.
ABC Methods will be renamed to 'A', 'B', 'C', 'D', ..., 'AA', 'AB', etc.
123 Methods will be renamed to '1', '2', '3', ..., '00', '01', etc.
keywords Allatori will use Java reserved keywords ('if', 'for', 'int', etc.) as method names. Such naming is legal in class file format, but can confuse many decompilers. However, this makes the resulting jar file bigger comparing to compact naming.
real Usually, some methods are not renamed according to configuration rules. Allatori will take these methods's names and give them to renamed methods, making the difference between new and original names unclear. Can be combined with other methods naming options (if it runs out of names, then the second option will be used).
custom(filename.txt) Names will be constructed using the provided text file. Each line of the file represents a single name element. If the file has two lines '0' and '1', then the generated names would be '0', '1', '00', '01', '10', '11', '000', etc.
unique Shortcut for unique-renaming property. Can be combined with other methods naming options. If any two methods have the same name and signature, then these methods will be renamed to the same new name. If any two methods have different name/signature, then these methods will have different names after renaming. It ensures consistency during subsequent incremental obfuscation runs.

Example:

    <property name="methods-naming" value="keywords"/>


1.6.4.6 fields-naming

Value Description
compact (default) Allatori will use single-character names as much as possible, thus making the resulting jar smaller.
iii All names will have the same length and differ in case only - iiii, iiiI, iiIi, etc. The resulting jar file will be bigger comparing to other renaming options.
abc Fields will be renamed to 'a', 'b', 'c', 'd', ..., 'aa', 'ab', etc.
ABC Fields will be renamed to 'A', 'B', 'C', 'D', ..., 'AA', 'AB', etc.
123 Fields will be renamed to '1', '2', '3', ..., '00', '01', etc.
keywords Allatori will use Java reserved keywords ('if', 'for', 'int', etc.) as field names. Such naming is legal in class file format, but can confuse many decompilers. However, this makes the resulting jar file bigger comparing to compact naming.
real Usually, some fields are not renamed according to configuration rules. Allatori will take these fields's names and give them to renamed fields, making the difference between new and original names unclear. Can be combined with other fields naming options (if it runs out of names, then the second option will be used).
custom(filename.txt) Names will be constructed using the provided text file. Each line of the file represents a single name element. If the file has two lines '0' and '1', then the generated names would be '0', '1', '00', '01', '10', '11', '000', etc.
unique All renamed fields will have unique names. Can be combined with other fields naming options.

Example:

    <property name="fields-naming" value="keywords"/>


1.6.4.7 classes-naming-prefix

Value Description
any string The specified string will be used as a name prefix for all renamed classes.

Example:

    <property name="classes-naming-prefix" value="c_"/>

Possible usage is specifying MainClass$ as a prefix:

    <property name="classes-naming-prefix" value="MainClass$"/>

Some decompilers will see renamed classes as inner classes of MainClass.



1.6.4.8 methods-naming-prefix

Value Description
any string The specified string will be used as a name prefix for all renamed methods.

Example:

    <property name="methods-naming-prefix" value="m_"/>


1.6.4.9 fields-naming-prefix

Value Description
any string The specified string will be used as a name prefix for all renamed fields.

Example:

    <property name="fields-naming-prefix" value="f_"/>


1.6.4.10 local-variables-naming

Value Description
optimize (default) Allatori performs optimizations to reduce the total number of local variables in a method. The remaining local variables will have the same name (single-name renaming option). This is the default and recommended option.
single-name Almost all local variables will have the same name. It is allowed by the Java virtual machine but can confuse a lot of decompilers.
abc Local variables will be renamed to unique names 'a', 'b', 'c', 'd', etc.
remove The original local variable names will be removed. It can reduce the size of the resulting jar.
keep-parameters Parameter names will be kept unchanged, all other local variables will be renamed. It is useful for methods that are part of the public API. There is also an option to keep parameters only in the specified methods using method tag in the keep-names section.
keep All local variable names will be kept unchanged. This option is not recommended.

Example:

    <property name="local-variables-naming" value="single-name"/>

The default single name for single-name and optimize renaming options is 'a'. You can change it using one of the following lines:

    <property name="local-variables-naming" value="optimize:ANY_OTHER_NAME"/>
    <property name="local-variables-naming" value="optimize:int"/>
    <property name="local-variables-naming" value="single-name:4"/>


1.6.4.11 skip-renaming

Value Description
disable (default) Allatori performs renaming of classes, methods and fields according to keep-names rules.
enable All classes, methods and fields will not be renamed. Local variables naming is controlled separately by local-variables-naming property. String encryption, flow obfuscation, etc. will be applied normally according to the settings in the configuration file.

Example:

    <property name="skip-renaming" value="enable"/>


1.6.4.12 update-resource-names

Value Description
disable (default) Resource file names will not be changed.
enable Resource files will be renamed to reflect changes in class names. If a resource file name is based on a class name, and that class is renamed, then the resource file will also be renamed.

Example:

    <property name="update-resource-names" value="enable"/>


1.6.4.13 update-resource-contents

Value Description
disable (default) Resource file contents will not be changed.
enable Resource contents will be updated to reflect changes in class names.
enable:ENCODING Resource contents will be updated to reflect changes in class names using the specified encoding. The default encoding is UTF-8.

Example:

    <property name="update-resource-contents" value="enable"/>
    <property name="update-resource-contents" value="enable:UTF-8"/>

The property can be applied to the specified files using apply2file attribute:

    <property name="update-resource-contents" value="enable" apply2file="*.xml"/>


1.6.5 Other properties
1.6.5.1 line-numbers

Value Description
obfuscate (default) Debug information is obfuscated and cannot be used without further transformation. Allatori has a special utility, which allows reconstructing the original stack trace with the help of an obfuscated one.

Reported stack trace will look like this:
  java.lang.NullPointerException
        at com.company.c.a(m:61)
        at com.company.b.b(w:94)
        at com.company.b.a(w:83)
        at com.company.a.a(n:75)

After transforming it with Allatori Stack Trace Utility, stack trace will look like this:
  java.lang.NullPointerException
        at com.company.Util.createTestException(Util.java:38)
        at com.company.TraceTest.testNullObject(TraceTest.java:53)
        at com.company.TraceTest.allTraceTests(TraceTest.java:14)
        at com.company.Main.runTest(Main.java:27)

Using this option makes the resulting jar smaller.
remove This option can be used, when the size of your application matters really much.

Reported stack trace will look like this:
  java.lang.NullPointerException
        at com.company.c.a(Unknown Source)
        at com.company.b.b(Unknown Source)
        at com.company.b.a(Unknown Source)
        at com.company.a.a(Unknown Source)
keep Leaves debug information without modifications. This option can be helpful for internal testing of your application. In other cases it's better to choose other options.

Reported stack trace will look like this:
  java.lang.NullPointerException
        at com.company.c.a(Util.java:38)
        at com.company.b.b(TraceTest.java:53)
        at com.company.b.a(TraceTest.java:14)
        at com.company.a.a(Main.java:27)

Example:

    <property name="line-numbers" value="obfuscate"/>


1.6.5.2 generics

Value Description
keep (default) If you are using reflection to determine generic types or need to compile other classes using the obfuscated jar as a library, then you need to keep generic type signatures.
remove Generic types information will be removed, i.e. a vector of strings Vector<String> will be seen as a generic Vector. It doesn't affect the performance, makes jar smaller, and is the recommended option.

Example:

    <property name="generics" value="remove"/>

This property can be set for the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Keeping generic types information in com.abc package's classes -->
<property name="generics" value="keep" apply2class="class com.abc.*"/>
<!-- Removing generic types information in all other classes -->
<property name="generics" value="remove"/>


1.6.5.3 inner-classes

Value Description
keep (default) Java compiler adds informational attributes with inner classes names. These attributes will be kept in obfuscated classes.
remove Informational attributes will be removed, class hierarchy will be harder to restore. It doesn't affect the performance, makes jar smaller, and is the recommended option.

Example:

    <property name="inner-classes" value="remove"/>

This property can be set for the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Keeping inner classes information in com.abc package's classes -->
<property name="inner-classes" value="keep" apply2class="class com.abc.*"/>
<!-- Removing inner classes information in all other classes -->
<property name="inner-classes" value="remove"/>


1.6.5.4 throws-clause

Value Description
keep (default) Keep methods' throws declarations.
remove JVM allows throwing exceptions without declaring them via throws keyword. The idea is similar to Lombok's sneaky throws, but used for obfuscation purposes.

Example:

    <property name="throws-clause" value="remove"/>

This property can be set for the specified classes/methods using apply2class and/or apply2method attributes. The apply2class attribute has the same format as template attribute of the class tag. The apply2method attribute has the same format as template attribute of the method tag. Here is an example:

    
<!-- Removing throws in all private methods -->
<property name="throws-clause" value="remove" apply2method="private *(**)"/>
<!-- Removing throws in com.abc package's classes -->
<property name="throws-clause" value="remove" apply2class="class com.abc.*"/>


1.6.5.5 member-reorder

Value Description
enable (default) Usually, developers place related methods and fields one after the other in the source file. This sequence is kept after the compilation process. Allatori will shuffle fields and methods.
random The same as enable.
alphabetical Fields and methods will be put in alphabetical order.
reverse-alphabetical Fields and methods will be put in reverse alphabetical order.
disable Member reordering is disabled.

Example:

    <property name="member-reorder" value="random"/>

This property can be set for the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Reordering members in com.abc package's classes -->
<property name="member-reorder" value="random" apply2class="class com.abc.*"/>
<!-- No reordering in all other classes -->
<property name="member-reorder" value="disable"/>


1.6.5.6 finalize

Value Description
disable (default) Class finalizing is disabled.
enable Classes with no subclasses (leaf classes) will be declared final. This feature should be used only for obfuscating stand-alone applications. It can make your application run faster.

Example:

    <property name="finalize" value="enable"/>


1.6.5.7 version-marker

Value Description
valid Java identifier name Allatori will use the given identifier as a name for some renamed methods and fields. This will mark the obfuscated class files. You can use it to mark the demo version of your product. For instance, Allatori demo version is marked with "ALLATORI_DEMO" string. Note that demo version of Allatori marks obfuscated jars and adds "ALLATORI_DEMO_" to whatever you use as a value of this property.

Example:

    <property name="version-marker" value="THIS_IS_DEMO_VERSION"/>


1.6.5.8 synthetize-methods

Value Description
private (default) All private methods will be marked as synthetic.
all All methods will be marked as synthetic.
package All package visible methods will be marked as synthetic.
protected All protected methods will be marked as synthetic.
public All public methods will be marked as synthetic.
disable Allatori will not mark methods as synthetic.

Some decompilers do not output synthetic methods.

Example:

    <property name="synthetize-methods" value="all"/>

The property can be used more than once:

    <property name="synthetize-methods" value="private"/>
    <property name="synthetize-methods" value="package"/>
    <property name="synthetize-methods" value="protected"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="synthetize-methods" value="all" apply2class="class com.abc.*"/>
    <property name="synthetize-methods" value="private"/>


1.6.5.9 synthetize-fields

Value Description
disable (default) Allatori will not mark fields as synthetic.
all All fields will be marked as synthetic.
private All private fields will be marked as synthetic.
package All package visible fields will be marked as synthetic.
protected All protected fields will be marked as synthetic.
public All public fields will be marked as synthetic.

Some decompilers do not output synthetic fields.

Example:

    <property name="synthetize-fields" value="all"/>

The property can be used more than once:

    <property name="synthetize-fields" value="private"/>
    <property name="synthetize-fields" value="package"/>
    <property name="synthetize-fields" value="protected"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="synthetize-fields" value="all" apply2class="class com.abc.*"/>
    <property name="synthetize-fields" value="private"/>


1.6.5.10 set-methods-to-public

Value Description
disable (default) Allatori will not mark methods as public.
all All methods will be marked as public. Marking private methods as public could break the functionality of your application.
private All private methods will be marked as public. Marking private methods as public could break the functionality of your application.
package All package visible methods will be marked as public.
protected All protected methods will be marked as public.



Example:

    <property name="set-methods-to-public" value="all"/>

The property can be used more than once:

    <property name="set-methods-to-public" value="package"/>
    <property name="set-methods-to-public" value="protected"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="set-methods-to-public" value="all" apply2class="class com.abc.*"/>
    <property name="set-methods-to-public" value="protected"/>


1.6.5.11 set-fields-to-public

Value Description
disable (default) Allatori will not mark fields as public.
all All fields will be marked as public.
private All private fields will be marked as public.
package All package visible fields will be marked as public.
protected All protected fields will be marked as public.



Example:

    <property name="set-fields-to-public" value="all"/>

The property can be used more than once:

    <property name="set-fields-to-public" value="package"/>
    <property name="set-fields-to-public" value="protected"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="set-fields-to-public" value="all" apply2class="class com.abc.*"/>
    <property name="set-fields-to-public" value="protected"/>


1.6.5.12 remove-toString

Value Description
disable (default) toString methods would not be removed.
enable Allatori will remove toString() method in obfuscated classes.
toString method can reveal some information about the class and is often used for debug only, therefore it can be removed.

Example:

    <property name="remove-toString" value="enable"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="remove-toString" value="enable" apply2class="class com.abc.*"/>
    <property name="remove-toString" value="enable" apply2class="class com.xyz.*"/>


1.6.5.13 remove-calls

Value Description
ClassName.methodName Allatori will remove calls to the specified method. Could be used to remove debug logging calls. ClassName and methodName can contain * to match several classes/methods.
If method has a return value, then the return value is replaced with null (0, false) and Allatori prints out a warning during the obfuscation.

Examples:

    <property name="remove-calls" value="android.util.Log.d"/>
    <property name="remove-calls" value="android.util.Log.*"/>

    // if a call to methodOne() is removed, then the line
    int i = methodOne(); 
    // would be changed to
    int i = 0;

    // if a call to methodTwo() is removed, then the line
    Object o = methodTwo();
    // would be changed to
    Object o = null;

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Removing Logger.debug calls from classes in com.abc package -->
<property name="remove-calls" value="com.package.Logger.debug" apply2class="class com.abc.*"/>


1.6.5.14 remove-annotations

Value Description
AnnotationClassName Allatori will remove AnnotationClassName annotations. Could be used to remove unnecessary/debug annotations. AnnotationClassName can contain * to match several classes.

Examples:

    <property name="remove-annotations" value="kotlin.Metadata"/>
    <property name="remove-annotations" value="com.package.annotations.*"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    
<!-- Removing com.package.Annotation annotations from classes in com.abc package -->
<property name="remove-annotations" value="com.package.Annotation" apply2class="class com.abc.*"/>


1.6.5.15 output-jar-compression-level

Value Description
0-9 Sets compression level for output jar files. 0 is no compression, 9 is the highest level of compression. Direct mapping to ZipOutputStream.setLevel(int)

Examples:

    <property name="output-jar-compression-level" value="9"/>


1.6.5.16 output-jar-duplicate-name-entries

Value Description
remove (default) If input jar contains several files with the same name in one folder, Allatori will put just one file in the output jar.
keep Allatori will write all duplicate name jar entries to the output jar. Zip(jar) file format allows having duplicate name entries, however standard Java API doesn't allow writing such entries. Allatori needs access to java.util.zip.ZipOutputStream.names private field to overcome this, so JVM should be run with
--add-opens java.base/java.util.zip=ALL-UNNAMED
option when running Allatori on Java 16+ or
--illegal-access=permit
option on older Java versions.

Examples:

    <property name="output-jar-duplicate-name-entries" value="keep"/>


1.6.6 Incremental obfuscation properties
1.6.6.1 incremental-obfuscation

Value Description
name of the previously created log file Sets the log file of the previous Allatori run. Relative paths are resolved against configuration file location.

Incremental obfuscation is used when you need to create a patch or add-on to your application. In such case you need guarantee, that new names of classes, methods and fields are consistent with the previously obfuscated version. Using log file generated during the previous run of Allatori as input when obfuscating the next release, makes these two releases fully compatible. So a patch or add-on can be seamlessly integrated into the previously deployed application.

When using incremental obfuscation you should include in the obfuscation process all your classes even if only some of them are to be distributed.

Example:

    <property name="incremental-obfuscation" value="input-renaming-log.xml"/>


1.6.6.2 unique-renaming

Value Description
disable (default) Unique renaming is disabled.
enable If any two methods have the same name and signature, then these methods will be renamed to the same new name. If any two methods have different name/signature, then these methods will have different names after renaming. It ensures consistency during subsequent incremental obfuscation runs.

Example:

    <property name="unique-renaming" value="enable"/>

The property can be applied to the specified classes using apply2class attribute. The apply2class attribute has the same format as template attribute of the class tag. Here is an example:

    <property name="unique-renaming" value="enable" apply2class="class com.abc.*"/>


1.7 Ignore-classes tag

The ignore-classes tag is used to completely exclude some classes from the obfuscation process. These classes are copied "as is" with no changes to the output jar file. Note that ignored classes will reference other classes by their original names. You cannot rename classes/methods referenced by ignored classes.

The tag contains nested class tags which are the same as
class tags in the keep-names section.

Example:

    <ignore-classes>
        <class template="class com.company.abc.*"/>
        <class template="class com.company.xyz.SomeClass"/>
    </ignore-classes>


2 Annotations

Annotation classes are located in the allatori-annotations.jar. All Allatori annotations are removed during the obfuscation process, so you don't need this jar file in the runtime. Annotations are used for easier and more accurate configuration of the obfuscator.

Here all are available annotations located in the com.allatori.annotations package:

Annotation Applicable to Description
Rename classes, methods and fields Instructs Allatori to rename the annotated element. Overrides configuration file settings.
DoNotRename classes, methods and fields Instructs Allatori not to rename the annotated element. Overrides configuration file settings.
StringEncryption classes Possible values are:
    StringEncryption.ENABLE
    StringEncryption.DISABLE
    StringEncryption.MAXIMUM
    StringEncryption.MAXIMUM_WITH_WARNINGS
Overrides string-encryption property. Example:
@StringEncryption(StringEncryption.ENABLE)
StringEncryptionType classes Possible values are:
    StringEncryptionType.FAST
    StringEncryptionType.STRONG
Overrides string-encryption-type property. Example:
@StringEncryptionType(StringEncryptionType.STRONG)
ControlFlowObfuscation classes and methods Possible values are:
    ControlFlowObfuscation.ENABLE
    ControlFlowObfuscation.DISABLE
Overrides control-flow-obfuscation property. Example:
@ControlFlowObfuscation(ControlFlowObfuscation.ENABLE)
ExtensiveFlowObfuscation classes and methods Possible values are:
    ExtensiveFlowObfuscation.DISABLE
    ExtensiveFlowObfuscation.NORMAL
    ExtensiveFlowObfuscation.MAXIMUM
Overrides extensive-flow-obfuscation property. Example:
@ExtensiveFlowObfuscation(ExtensiveFlowObfuscation.MAXIMUM)


3 Android obfuscation

Allatori performs full-featured obfuscation of Android applications and can be easily integrated into the build process. We've created a typical configuration file for Android projects, making it very easy to obfuscate Android application. You can find the configuration file (allatori.xml) and sample build files (build.gradle and build.xml) in the tutorial that comes with Allatori distribution.


3.1 Using Android Studio

Here are three steps to set up Allatori for your Android Studio project:
  1. Create allatori folder in your rootDir folder. Copy allatori.jar to the created folder;
  2. Copy allatori.xml to your projectDir folder (where project's build.gradle is) from our tutorial;
  3. Edit build.gradle:
android {
    ...
    // for applications
    applicationVariants.all { variant ->
        variant.javaCompileProvider.get().doLast {
            runAllatori(variant)
        }
    }
    // for libraries
    // libraryVariants.all { variant ->
    //    variant.javaCompileProvider.get().doLast {
    //        runAllatori(variant)
    //     }
    // }
}

def runAllatori(variant) {
    copy {
        from "$projectDir/allatori.xml"
        into "$buildDir/intermediates/classes/"
        expand(classesRoot: variant.javaCompileProvider.get().destinationDir,
                kotlinRoot: "${buildDir}/tmp/kotlin-classes/${variant.name}",
                androidJar: "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar",
                classpathJars: variant.javaCompileProvider.get().classpath.getAsPath(),
                logFile: "allatori-log-${variant.name}.xml")
        rename('allatori.xml', "allatori-${variant.name}.xml")
    }

    new File("${variant.javaCompileProvider.get().destinationDir}-obfuscated").deleteDir()
    javaexec {
        main = 'com.allatori.Obfuscate'
        classpath = files("$rootDir/allatori/allatori.jar")
        args "$buildDir/intermediates/classes/allatori-${variant.name}.xml"
    }
    new File("${variant.javaCompileProvider.get().destinationDir}").deleteDir()
    new File("${variant.javaCompileProvider.get().destinationDir}-obfuscated").renameTo(new File("${variant.javaCompileProvider.get().destinationDir}"))

    // Kotlin support
    // new File("${buildDir}/tmp/kotlin-classes/${variant.name}").deleteDir()
    // new File("${buildDir}/tmp/kotlin-classes/${variant.name}-obfuscated").renameTo(new File("${buildDir}/tmp/kotlin-classes/${variant.name}"))
}


3.2 Using Ant

Here are three steps to set up Allatori for your Android Ant project:
  1. Create allatori folder in your project's folder. Copy allatori.jar to the created folder;
  2. Copy allatori.xml to your project's folder from our tutorial;
  3. Add the following target to your build.xml:
    <target name="-obfuscate" unless="do.not.compile">
        <taskdef name="allatori" classname="com.allatori.ant.ObfuscatorTask"
                                 classpath="allatori/allatori.jar"/>
        <delete dir="${out.classes.absolute.dir}-obfuscated"/>
        <allatori config="allatori.xml"/>
        <property name="out.dex.input.absolute.dir"
                  value="${out.classes.absolute.dir}-obfuscated"/>
    </target>

You may need to perform further configuration for your project. Properties defined in the Ant build file can be referenced from the Allatori configuration file using standard Ant syntax: ${PropertyName}.


4 Eclipse IDE plugin

Allatori can be easily used with Eclipse IDE:
  1. Copy allatori.jar to the eclipse/dropins folder;
  2. Right-click your project's name in Eclipse, choose Configure -> Add Allatori Builder in the popup menu (
see screenshot);
  3. Clean rebuild the project, obfuscation process runs only on clean builds.

The default allatori.xml configuration file will be created in the project's root folder during the first run.

You can use ${eclipse-input} and ${eclipse-classpath} properties in the configuration file:

    <input>
        ${eclipse-input}
    </input>

    <classpath>
        ${eclipse-classpath}
    </classpath>

Feel free to contact us with any questions.