YGuard

Using the yGuard Ant task, name obfuscation and code shrinking can be seamlessly integrated into your deployment process. The yguard task contains two nested elements that perform the name obfuscation and code shrinking separately:


 * The shrink element removes all code elements that are not reachable from the entrypoints given in the nested keep element.
 * The rename element performs name-obfuscation, renaming all packages, classes, methods and fields according to a selectable name-mapping scheme.

Elements can be excluded from the renaming process using a nested keep element.

Both elements operate on the same set of input and output files specified in the containing yguard element.

Links

 * yGuard website
 * Documentation

General Hints & Troubleshooting
The most important facts to keep in mind when using yGuard are described here briefly:

If your application is broken after using the shrink task, consider using the createStubs attribute of the shrink task to find out which additional entities you need to include in the keep element. To solve this problem, set the -Xmx option in the ANT_OPTS variable, e.g.:
 * If you use the rename task, code in the form of MyApplication.class will break if MyApplication will be obfuscated by name and the obfuscation switch replaceClassNameStrings is set to false. The shrink task will currently recognize code in the form of MyApplication.class only if the java files were compiled using an arbitrary version of the standard javac compiler (although the shrinking engine might recognize the .class construct also if the classes were compiled using a compiler that generates similar bytecode).
 * Automatic introspection and reflection will break in most cases, when you decide to obfuscate the corresponding methods and fields. If you use the shrink task and your application uses reflection you should explicitly designate all entities loaded per reflection as code entrypoints using the keep element.
 * Class.forName(className) will not work when using the rename task unless you use the obfuscated name string in your variable or the String is a local constant and replaceClassNameStrings is not set or set to true . If you use the shrink task, className should be contained in the list of entrypoints using the keep element.
 * The customized serialization mechanism will not work if you obfuscated or shrinked the writeObject and readObject methods as well as the serializationUID field.
 * Simple bean introspection will not work, if you decide to obfuscate your public accessor methods, since it makes use of reflection.
 * If you do not set the -Xmx property for the Java virtual machine, the yguard Ant task might fail due to a java.lang.OutOfMemoryError.

bash> export ANT_OPTS="-Xmx512M" or     cshell> setenv ANT_OPTS "-Xmx512M"

The yguard Element
The yguard task contains elements that define basic properties common to the nested rename and shrink tasks.

Child Elements:


 * inoutpair
 * externalclasses
 * attribute
 * rename
 * shrink

The inoutpair Elements
At least one inoutpair element has to be specified in order to run the yguard task. This elements specifies the paths to the input and output jar files.

Attributes:


 * in
 * specifies an exisiting jar file, which contains the unshrinked and unobfuscated .class files.


 * out
 * specifies a path to a jar file which will be created and used to put the results of the shrinking and obfuscation process.


 * resources
 * Will only be considered if the yguard element contains a nested shrink element. Values: copy, auto, none.

The externalclasses Element
If the jar to be processed by yGuard depends on external classes or libraries, this element can be used to specify classpaths to these entities. These libraries will neither be shrinked nor obfuscated. Use the inoutpair element for this purpose! See example 4 later in this document for an example of when to use this element. In order to achieve a maximum shrinking effect by the shrink task, all external dependencies should be declared in the externalclasses element. Otherwise, all non-private methods of classes that inherit from unresolvable classes will not be shrinked.

The shrink Element
The shrink task removes all classes, fields and methods that are not reachable from a number of entrypoints given by a nested keep element.

Child Elements:


 * keep
 * entrypointjar

The entrypointjar Element
The entrypointjar element can be used for convenience if your application uses libraries that are to be shrinked, but the jarfile using these libraries should be left untouched by the shrinking engine. Such a jarfile could be specified as an entrypointjar.

The attribute name informs the path to to the jar file to use as entrypointjar.

The rename Element
The basic idea is, that all elements will be renamed by this task. Using the nested keep element, you have to specify all classes, methods, fields, and attributes that should be excluded from name obfuscation, i.e. that will not be renamed but kept in the API. There are different use cases, where you sometimes want to exclude or simply just have to exclude some elements from name obfuscation. See the Complete Examples section for explanation of some common use cases. If your code uses reflection, please read the General Hints & Troubleshooting section for information on this topic. Excluding elements can be achieved by using both the keep element and the mainclass attribute of the rename element.

Child Elements:


 * keep
 * property
 * patch
 * adjust
 * map

The keep Element
This element is a child of the rename or shrink element. It can be used to specify elements that are excluded from the parent rename or shrink task. The excluded classes, methods and fields are defined using nested class, method and field elements. The elements given in the keep element are considered as code entrypoints. All code reachable from these entrypoints will be implicitly excluded from shrinking, too.

Common Child Elements:


 * class
 * method
 * field

Child Elements only available in the rename task:


 * sourcefile
 * linenumbertable

The class Element
The class element can be used for excluding certain classes and/or their fields and methods from the renaming or shrinking process. If no name, extends or implements attribute is given and the class element contains no nested patternset, a class element matches all class names.

Value/Visibility 	public  	protected  	friendly  	private none 			- 		- 		- 		- public 			* 		- 		- 		- protected 		* 		* 		- 		- friendly 		* 		* 		* 		- private 		* 		* 		* 		*

Child Elements:


 * patternset

Example 1: Getting started with Ant and yGuard (for Ant newbies)




        

 





 <include name="com.mycompany.publicapi.**.*"/> <exclude name="com.mycompany.publicapi.private.*"/> <include name="com.mycompany.menu.reflection.**.*"/>

<rename mainclass="${mainclass}" logfile="${renamelog}"> <property name="error-checking" value="pedantic"/>

<class classes="protected" methods="protected" fields="protected"> <include name="com.mycompany.publicapi.**.*"/> <exclude name="com.mycompany.publicapi.private.*"/>

<target name="compile" depends="init"> <javac srcdir="${srcDir}" includes="com/mycompany/**/*.java" destdir="${classDir}">

<target name="jar" depends="compile"> <jar jarfile="${jar}" basedir="${classDir}" includes="com/mycompany/**"> <fileset dir="${srcDir}"> <include name="com/mycompany/resources/*.properties"/>

<target name="run" depends="yguard"> <java classname="${mainclass}" fork="true"> <pathelement location="${obfjar}"/>

<target name="clean" depends="init"> <delete dir="${classDir}" includeEmptyDirs="true" />

Example 2: A Public API
<inoutpair in="classes.jar" out="classes_obf.jar"/> <inoutpair in="utils.jar" out="utils_obf.jar"/>

<attribute name="Deprecated"/>

<shrink logfile="shrinklog.xml"> <class classes="protected" methods="protected" fields="protected"/>

<rename mainclass="com.mycompany.myapp.Main" logfile="obflog.xml"> <class classes="protected" methods="protected" fields="protected"/>

Example 3: A Demo Program
<inoutpair in="demo.jar" out="demo_obf.jar"/>

<shrink logfile="shrinklog.xml">

<method name="void main(String[])" class="com.mycompany.myapp.Main" />

<class name="com.mycompany.myapp.data.DataObject" methods="public" fields="none"/> <class name="com.mycompany.myapp.data.InnerDataObject"/> <method name="void writeObject(java.io.ObjectOutputStream)"> <patternset id="datapatternset"> <include name="com.mycompany.myapp.data.*"/> <method name="void readObject(java.io.ObjectInputStream)"> <patternset refid="datapatternset"/> <field name="serialVersionUID"> <patternset refid="datapatternset"/>

<rename mainclass="com.mycompany.myapp.Main" logfile="renamelog.xml">

<property name="language-conformity" value="illegal"/> <property name="naming-scheme" value="mix"/> <class name="com.mycompany.myapp.data.DataObject" methods="public" fields="none"/> <class name="com.mycompany.myapp.data.InnerDataObject"/> <method name="void writeObject(java.io.ObjectOutputStream)"> <patternset refid="datapatternset" /> <method name="void readObject(java.io.ObjectInputStream)"> <patternset refid="datapatternset"/> <field name="serialVersionUID"> <patternset refid="datapatternset"/>

Example 4: A Program Using an External Library
<inoutpair in="mydemo.jar" out="mydemo_obf.jar"/>

<pathelement location="lib/external.jar"/> <pathelement location="lib/additional/classes/"/>

<shrink logfile="shrinklog.xml"> <property name="error-checking" value="pedantic"/> <method name="void main(String[])" class="com.mycompany.myapp.Main" />

<rename mainclass="com.mycompany.myapp.Main" logfile="renamelog.xml"> <property name="error-checking" value="pedantic"/>