This document explains how to use the yGuard Java obfuscation and shrinking software together with Ant. yGuard is a product of yWorks GmbH, creator of the outstanding JavaTM graph visualization framework yFiles and other fine products.

Documentation for the deprecated Ant syntax of previous yGuard releases is still available.

yGuard 2.5 Ant Task Documentation

Contents

Introduction

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:

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

Installation

In order to make use of yGuard's yguard task you must have Ant properly installed and configured to run it. After downloading and extracting the jar file (yguard.jar), place it in a path near to your build script. You may use absolute paths, but in the following example, we expect the jar file to lie in the same directory as your build file.

In order the get the Ant task running you should insert a couple of lines in your build script (build.xml):

    <target name="yguard">
      <taskdef name="yguard"
      classname="com.yworks.yguard.YGuardTask"
      classpath="yguard.jar"/>
      <yguard>
        <!-- insert your yguard elements here -->
      </yguard>
    </target>

For a complete build.xml file have a look at the examples section.

General Hints & Troubleshooting

There are a couple of things you should be aware of when obfuscating and shrinking software.
The weakest part of an application considering name obfuscation and code shrinking is code that uses reflection to dynamically load classes, invoke methods etc. Therefore, you have to be especially careful when using the yguard task on applications that rely on reflection.
The most important facts to keep in mind when using yGuard are described here briefly:

The yguard Element

The yguard task contains elements that define basic properties common to the nested rename and shrink tasks.
Please see the General Hints & Troubleshooting section to learn about common pitfalls when using name obfuscation and shrinking software.

Attributes

The yguard element has no attributes.

Child Elements

The inoutpair Elements

At least one inoutpair element or one non-empty inoutpairs element has to be specified in order to run the yguard tasks. This elements specifies the paths to the input and output jar files.

Attributes

Attribute Description Required
in specifies an exisiting jar file, which contains the unshrinked and unobfuscated .class files. Yes
out specifies a path to a jar file which will be created and used to put the results of the shrinking and obfuscation process. Yes
resources Will only be considered if the yguard element contains a nested shrink element.
Determines how the shrinking engine handles all non-.class files.
Currently the following three resource policies are supported:
  • copy: the default, simply copies all resource files to the output jar.
  • auto: copies only those resource files that reside in a directory that still contains one or more .class files after shrinking.
  • none: discards all resource files.
No, defaults to copy.

Child Elements

The inoutpair element has no child elements.

If multiple jar files need to be obfuscated at once the inoutpairs element can be used alternatively.

The inoutpairs Elements

Additionally or alternatively to inoutpair elements this element can be specified in order to specify the paths to the input and output jar files.

Attributes

Attribute Description Required
resources Will only be considered if the yguard element contains a nested shrink element.
Determines how the shrinking engine handles all non-.class files.
Currently the following three resource policies are supported:
  • copy: the default, simply copies all resource files to the output jar.
  • auto: copies only those resource files that reside in a directory that still contains one or more .class files after shrinking.
  • none: discards all resource files.
No, defaults to copy.

Child Elements

  • patternset
  • optionally a mapper that determines the name mapping between the unobfuscated and obfuscated versions of the jar files. Note that identitymapper and mergemapper are not supported. All matched jar file names need to be mapped to exactly one jar file name that differs from the original jar file.

Some examples:

  <!-- use all jars in the input-lib-dir directory and obfuscate them
          to *_obf.jar -->
  <inoutpairs resources="auto">
    <fileset dir="${input-lib-dir}">
      <include name="myapp*.jar"/>
      <exclude name="*_obf.jar"/>
    </fileset>
    <mapper type="glob" from="*.jar" to="*_obf.jar"/>
  </inoutpairs>

  <!-- the above mapper is the default one so the following snippet does the same -->
  <inoutpairs resources="auto">
    <fileset dir="${input-lib-dir}">
      <include name="myapp*.jar"/>
      <exclude name="*_obf.jar"/>
    </fileset>
  </inoutpairs>

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 elements attributes and child elements can be seen on the Ant documentation page about using path elements.

The attribute Element

Using the attribute element, you can specify which attributes present in the input classes should be kept in the obfuscated output classes.
See example 6 later in this document for an example of when to use this element.

Attributes

Attribute Description Required
name A comma-separated list of attribute names that are to be retained in the shrinked and/or obfuscated class files. Yes

Child Elements

An example:

    <attribute name="SourceFile, LineNumberTable, LocalVariableTable">
      <patternset>
        <include name="com.mycompany.mylibrary.**"/>
      </patternset>
    </attribute>

This will retain the attributes named "SourceFile", "LineNumberTable", and "LocalVariableTable" effectively enabling debugging information for all classes in the com.mycompany.mylibaray package and subpackages.

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.
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.

Attributes

Attribute Description Required
logfile Determines the name of the logfile that is generated during the shrinking process. The logfile contains information about the entrypoints the shrinking engine uses, the removed classes, methods and fields as well as any warnings.
If the name ends with a ".gz", yGuard will automatically create a gzipped version of the file which potentially saves a lot of disc space.
No, defaults to yshrinklog.xml
createStubs Instead of removing methods completely, this attribute causes the shrink task to insert a method stub that throws a java.lang.InternalError if it is called. This attribute is very useful if the shrinking process causes your application to break and you are uncertain about which additional code entities you have to include in the keep element.
Note that classes considered as completely obsolete by the shrinking engine are still removed completely - this attribute only affects obsolete methods of non-obsolete classes.
No, defaults to false

Child Elements

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.

Attributes

Attribute Description Required
name Path to to the jar file to use as entrypointjar. Yes

Child Elements

The entrypointjar element has no child elements.

Example

      <yguard>
        <inoutpair in="lib-in.jar" out="lib-out.jar" />
        <shrink>
          <entrypointjar name="myApp.jar"/>
        </shrink>
      </yguard>

The rename Element

The basic idea is, that all elements will be renamed by this task. There are different use cases, where you sometimes want to exclude or simply just have to exclude some elements from name obfuscation, i.e. not rename them but keep in the API as is. 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 the keep element, the mainclass attribute of the rename element and by annotating elements in the source code with the annotation that is specified in the annotationClass attribute of the rename element. Using the nested keep element, you have to specify all classes, methods, fields, and attributes that should be excluded from name obfuscation. Another way is to annotate the elements directly in the source code that should be obfuscated or excluded. You can use the yFiles obfuscation annotation com.yworks.util.annotation.Obfuscation for that or specify your own annotation in the annotationClass attribute of this element.

Attributes

Attribute Description Required
mainclass Can be used as a shortcut to specify the mainclass of your application. Both the class name and the main method will be excluded from name obfuscation. Alternatively you may want to consider to exclude the main method only. If your jar contains a Main-Class attribute, the rename task will automatically adjust the value to the obfuscated name. No
logfile Determines the name of the logfile that is generated during the renaming process. The logfile contains information about the mappings the name obfuscator generates as well as any warnings.
If the name ends with a ".gz", yGuard will automatically create a gzipped version of the file which potentially saves a lot of disc space.
No, defaults to yguardlog.xml
conservemanifest a boolean attribute (valid values: true/false) that determines whether the manifest file of the jars should be left untouched by the renaming engine. If set to false, the manifest will be modified to reflect the new message digests. No, defaults to false.
replaceClassNameStrings a boolean attribute (valid values: true/false) that determines whether the renaming engine should try to replace hardcoded Strings, which are used in conjunction with the MyClass.class construct. If set to false, those Strings will be left untouched and code of the form MyClass.class will break if MyClass gets obfuscated by name. If set to true (the default), yGuard will try to workaround this problem by replacing the hardcoded String with the appropriate obfuscated name. However this will only work if the unobfuscated class file has been generated with the usual compilers ('javac', 'jikes' and 'bjc') or compilers, that produce similar bytecode. This can also have the side-effect of modifying too many Strings, e.g if you have code that looks like System.out.println("com.mycompany.MyClass");, it might get replaced, if MyClass.class resides in the very same class with something like System.out.println("com.A.OoO");. It will most likely fail if the class has been previously obfuscated by another obfuscation tool or a different compiler has been used for compilation. Anyway it is always worth it to give it a try, if you want to have 'full obfuscation'. No, defaults to true
annotationClass Specifies the name of the annotation class that can be used to exclude elements by annotating them in the source code. The specified annotation can be any annotation that fits the convention. No, defaults to com.yworks.util.annotation.Obfuscation

Child Elements

The property Elements

property elements can be used to give hints to the name obfuscation engine. Depending on the exact version of yGuard, the task may use these hints to control the process of obfuscation.

Attributes

Attribute Description Required
name specifies a key which may be interpreted by the obfuscation task. Yes
value specifies the corresponding value of the property. Yes

The following properties are supported:

Name Description
error-checking can be used to tell yGuard to bail out if it detects any problems. Currently this property can be set to the following value:
  • pedantic will make the obfuscation run fail, i.e. the target which uses the rename element will fail, if yGuard detects any problems.
naming-scheme Can be used to tell the renaming engine to use a different naming scheme during the obfuscation. Currently this property can be set to one of the following values:
  • smallWill produce very short names, i.e. the resulting jar file will be as small as possible.
  • bestWill produce names, that are very likely to be misunderstood by decompilers and disassemblers. Using this naming-scheme it is even impossible on most filesystems to successfully unjar or unzip the resulting jar file (Windows, Standard Unix, Standard Linux, MacOS). However this scheme takes up a lot of space and the resulting jar is likely to become large (typically roughly double the size).
  • mixIs a mixture of both the other two values, which leads to reasonable small but still hard to decompile jar files.
language-conformity Can be used to advise the renaming engine to produce names, that should be decompilable by most decompilers. On the other hand, yGuard can produce class files that should be executable and verifiable by all of todays virtual machines, but produces absolutely nonsense names when decompiled (Ever tried to compile 'int class = false.this super(String$super.init if);' ?!) Currently this property can be set to one of the following values:
  • compatibleWill produce names, that are ok for (most) decompilers, java, jar and manifest files and can be unzipped to most filesystems.
  • legalWill produce names, that are ok for (some) decompilers, java, jar and manifest files.
  • illegalWill produce names, that will crash some tools but usually not the jvm, but JBuilder7 in many occasions for example.
overload-enabled Determines whether the renaming engine tries to use the same names for methods with different signatures or whether it always generates unique method names. Setting this property to false eases the analysis of stacktraces but reduces the obfuscation effect.
obfuscation-prefix Can be used to instruct the renaming engine to prefix packages, that are fully obfuscated with a given package prefix, e.g. com.mycompany.obf.
digests Can be used to tell yGuard which digest algorithms should be used for the digest generation in the manifest file. Valid values are either none, or a comma-separated list of digest-algorithm identifiers, e.g. SHA-1, MD5 (which is the default).
expose-attributes Can be used to give yGuard a list of attributes yGuard should expose in addition to the standard attributes. By default yGuard removes unneeded attributes like "Deprecated" from methods. The value can be a comma separated list of attributes as defined in Section 4.7 of the VM Specification of the .class File Format. E.g. in order to keep the "Deprecated" attribute one can add the following property:
<property name="expose-attributes" value="Deprecated"/>
Note that this affects all classes which will be obfuscated. For a better control of which attributes should be exposed in what classes use the Attribute Element.

Child Elements

The property element has no child elements.

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 package, 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.

Attributes

The keep element provides a number of boolean attributes that determine whether debug information and annotations present in the input class files are to be retained in the output files. The default behavior of the rename and shrink elements for the respective attributes is explained in the table below.
Note that a more fine-grained control over which attributes to keep for which class files is possible using the attribute element. Also, the attribute element allows to define attributes to keep for both the rename and the shrink element in a common place.

Attribute Description Default (rename) Default (shrink)
sourcefile Determines whether the name of the original source code file should be included in the output class files. remove remove
linenumbertable Determines whether the line number table, that contains a mapping from each opcode in the class file to the line number in the original source code file should be included in the output class files. remove remove
localvariabletable Determines whether the local variable table, that contains a mapping from each local variable in the class file to the name that has been used in the original source code file should be included in the output class files. remove remove
localvariabletypetable Determines whether the local variable type table, that contains a mapping from each local variable in the class file to the name and its generic type signature that has been used in the original source code file should be included in the output class files. remove remove
runtimevisibleannotations Determines whether annotations with the retention policy RetentionPolicy.RUNTIME should be included in the output class files. keep keep
runtimevisibleparameterannotations Determines whether method paramater annotations with the retention policy RetentionPolicy.RUNTIME should be included in the output class files. keep keep
runtimeinvisibleannotations Determines whether annotations with the retention policy RetentionPolicy.CLASS should be included in the output class files. keep remove
runtimeinvisibleparameterannotations Determines whether method paramater annotations with the retention policy RetentionPolicy.CLASS should be included in the output class files. keep remove

Common Child Elements

Child Elements only available in the rename task

The rename task allows for a special treatment of the linenumbertable and sourcefile attributes. This treatment can be specified in the following child elements:

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.

The classes, methods and fields attributes tell the shrinking and renaming engines which classes, methods and fields to keep based on their visibility. The following table lists the possible values for all of these attributes and shows which elements will be excluded. A '*' denotes, that elements that have the given visibility will be excluded for the specified attribute value. A '-' denotes that the these elements will not be excluded from the process.


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

Attributes

Attribute Description Required
name The name of the class to be kept. No
classes The visibility of the classes to be kept. No, defaults to none
methods The visibility of the methods to be kept. No, defaults to none
fields The visibility of the fields to be kept. No, defaults to none
extends If no name attribute is given, keeps all classes that equal or extend the class defined by the given fully qualified classname.
See example 7 for an example usage of this attribute.
No
implements If no name attribute is given, keeps all classes that equal or implement the class defined by the given fully qualified classname.
See example 7 for an example usage of this attribute.
No

Child Elements

Explanation

There are three possible ways of specifying which classes will be excluded from the shrinking and obfuscation process:

  1. One can specify a single java class using the fully qualified name in java syntax with the name attribute. For example:
    <class name="mypackage.MyClass"/>
  2. One can specify multiple java classes using a modified version of a patternset. The patternset's includes and excludes element should use java syntax, but the usual wildcards are allowed. Some examples:
          <class>
            <patternset>
              <include name="com.mycompany.**.*Bean"/>
              <exclude name="com.mycompany.secretpackage.*"/>
              <exclude name="com.mycompany.myapp.SecretBean"/>
            </patternset>
          </class>
    This will expose all classes which reside in the package subtree of com.mycompany and whose name ends with Bean except for those, that reside in the com.mycompany.secretpackage package and the single SecretBean in com.mycompany.myapp.
          <class>
            <patternset>
              <include name="com.mycompany.myapp.MainClass"/>
              <include name="org.w3c.sax?."/>
              <exclude name="org.w3c.sax?.**.*$$*"/>
            </patternset>
          </class>
    This will expose the MainClass class and all classes, which reside in packages like org.w3c.sax1, org.w3c.sax2, org.w3c.saxb except for inner classes. '$' is used as a separator between outer class names and inner class names. Since Ant uses '$' as an escape character, you have to use two consecutive '$'s ('$$') if you want to pass one as an argument to the task.
  3. Finally one can specify classes depending on their visibility, i.e. depending whether they have been declared public, protected, package friendly or private (inner classes). This can be achieved by additionally specifying the classes attribute in the class element.
          <class classes="protected">
            <patternset>
              <include name="com.mycompany.myapi."/>
            </patternset>
          </class>
    This will keep all class names, that are either public or protected and which reside in one of the subpackages of com.mycompany.myapi (note the abbreviation: the trailing dot behaves like the trailing '/' in the usual patternset, i.e. it could be rewritten as com.mycompany.myapi.**.*)
          <class classes="protected"
            methods="protected"
            fields="protected">
            <patternset>
              <include name="**.*"/>
            </patternset>
          </class>
    This example shows the very common use case of excluding a complete public API from the shrinking and obfuscation process. There is an abbreviation for this use case: you can omit the patternset element, since in the case where the classes attribute is specified and there is no patternset child element used, the task will automatically apply this rule. In this example all classes will be exposed, that are either public or protected. Their methods and fields will be exposed as long as they are declared public or protected. If a class is package friendly or private (inner classes), neither itself nor its methods or fields will be exposed.

    The last example shows how to keep the public methods of certain classes only, but neither field names nor the class names themselves.

          <class classes="none" methods="public" fields="none">
            <patternset>
              <include name="com.mycompany.myapi."/>
            </patternset>
          </class>

The method Element

Using the method element you can specify methods by signature which should be excluded from shrinking or name obfuscation.

Attributes

Attribute Description Required
name Specifies the method to keep. Use the complete signature using fully qualified class names and the return type! Yes
class Specifies the class which contains the method. Use the normal java syntax, i.e. the fully qualified name. This attribute can be omitted, if the patternset element is used as a child element, in which case all classes matching the patternset will be searched and their corresponding methods will be kept. No

Child Elements

Examples

    <method class="com.mycompany.myapp.MyClass"
      name="void main(java.lang.String[])"/>
    <method class="com.mycompany.myapp.MyClass"
      name="int foo(double[][], java.lang.Object)"/>
    <method name="void writeObject(java.io.ObjectOutputStream)">
      <patternset>
        <include name="com.mycompany.myapp.data.*"/>
      </patternset>
    </method>
    <method name="void readObject(java.io.ObjectInputStream)">
      <patternset>
        <include name="com.mycompany.myapp.data.*"/>
      </patternset>
    </method>

This will keep the main method of the MyClass class and the foo method. Additionally all readObject and writeObject methods (used for Serialization) will be kept in all classes of the com.mycompany.myapp.data package. Note that you have to specify the return argument's type, even if it is void and that you have to use the fully qualified name for all classes, even those, that are in the java.lang package.

The field Element

Using the field element you can specify fields by name which should be excluded from shrinking or name obfuscation.

Attributes

Attribute Description Required
name specifies the field to keep. Use the name of the field only, do not include its type! Yes
class Specifies the class which contains the field. Use the normal java syntax, i.e. the fully qualified name. This attribute can be omitted, if the patternset element is used as a child element, in which case the all classes matching the patternset will be searched and their corresponding fields will be kept. No

Child Elements

Examples

    <field class="com.mycompany.myapp.MyClass" name="field"/>
    <field name="serialVersionUID">
      <patternset>
        <include name="com.mycompany.myapp.data.*"/>
      </patternset>
    </field>

This will keep the field named 'field' of the MyClass class. Additionally all the serialVersionUID fields (used for Serialization) will be kept in all classes of the com.mycompany.myapp.data package.

The package Element

The package element can be used for excluding certain package's names from the renaming process. It cannot be used for the shrinking process.
All packages that are matched be the nested patternset element will not be obfuscated. This has no influence on the class, method, or field names but will only result in the package's name not being obfuscated. Normally, it is not necessary to use this element, instead the class element is used to keep class names (and thus their package names) from being obfuscated.

Child Elements

Examples

    <package>
      <patternset>
        <include name="com.mycompany.myapp.*"/>
      </patternset>
    </package>

This will keep the names of all packages that are direct descendants of com.mycompany.myapp. This will not influence the names of the classes contained in these packages.

The sourcefile Element

The sourcefile element allows for a special treatment of the sourceFile attribute by the rename element.
Using nested property elements, the mapping of sourceFile elements in obfuscated class files can be adjusted.

The following properties are supported:

Name Description
mapping the value of this property determines the name all sourceFile attributes matched by the sourcefile element are mapped to.

Child Elements

Examples

    <sourcefile>
      <property name="mapping" value="y"/>
      <patternset>
        <include name="com.mycompany.myapp.**"/>
      </patternset>
    </sourcefile>

This will map all of the source file attributes in the packages below com.mycompany.myapp to " y", which is small and generally a nice letter.

The linenumbertable Element

The linenumbertable element allows for a special treatment of the linenumbertable attribute by the rename.
Using nested property elements, the mapping of linenumbertable elements in obfuscated class files can be adjusted.

The following properties are supported:

Name Description
mapping-scheme can be used with the following two values:
  • scramble: this will use a non-trivial algorithm to scramble the line numbers in the existing file. The algorithm implemented uses for each class a different scrambling scheme. The optional scrambling-salt property can be used to provide an integer value that will be used to "salt" the algorithm's random seed for the scrambling. The size of the (uncompressed) .class file will not change using this mapping scheme.
  • squeeze: this will use a simple algorithm that virtually puts all of a methods code into the first line of code of the method. It will appear as if each method had been written in a single line of code. The advantage of this scheme is drastically reduced size requirements and thus smaller .class files, while at the same time it will be possible to unambiguously determine the exact method from a stacktrace.
scrambling-salt can be used in conjunction with mapping-scheme to provide an integer value that will be used to "salt" the algorithm's random seed for the scrambling.

Child Elements

  • property
  • patternset

Examples

  <linenumbertable>
    <patternset>
      <include name="com.mycompany.myapp.**"/>
    </patternset>
  </linenumbertable>

This will keep the line numbers of all the classes in the com.mycompany.myapp packages and subpackages. Note that in order to see the line numbers in stacktraces, the sourcefile attribute has to be retained for those files, too, since otherwise the JDK will display "Unknown source. " for the stack elements.

  <linenumbertable>
    <property name="mapping-scheme" value="scramble"/>
    <property name="scrambling-salt" value="1234"/>
    <patternset id="CompanyPatternSet">
      <include name="com.mycompany.myapp.**"/>
    </patternset>
  </linenumbertable>
  <sourcefile>
    <property name="mapping" value="y"/>
    <patternset refid="CompanyPatternSet"/>
  </sourcefile>

This will keep scrambled line numbers for all classes found in and below the com.mycompany.myapp packages. The scrambling algorithm will use the given "salt" value to use a predefined scrambling scheme. In order to see the scrambled line numbers, a sourcefile element is used on the same patternset, which is referenced by its previously declared reference id, to rename the source files to "y".

The adjust Element

Using the adjust element one can specify resource files whose names and/or contents should be adjusted by the rename engine to reflect the obfuscated class names.
Note: This will only adjust files that are part of the inoutpair jars! I.e. the fileset's root directory is the combined root of all jars that are passed to yGuard via the inoutpair elements. yGuard will not modify any of the files on disk, except for the out-jar!

Attributes

Attribute Description Required
replaceName specifies whether or not the names of the specified resources should be adjusted. No, defaults to false
replaceContent specifies whether or not the contents of resource files should be adjusted. No, defaults to false
replacePath specifies whether or not the paths to the resource files should be adjusted. No, defaults to true

Child Elements

The adjust element can be used just like the standard Ant ZipFileSet element.

Some examples:

    <!-- adjust the names of all java property files in the jars -->
    <adjust replaceName="true">
      <include name="**/*.properties"/>
    </adjust>

    <!-- adjust the classnames specified within a single XML file in the jar -->
    <adjust file="plugins.xml" replaceContent="true" />

    <!-- suppress the adjustment of the resource path
    com/mycompany/myapp/resource in the jar. -->
    <!-- the package com.mycompany.myapp still gets obfuscated. -->
    <adjust replacePath="false">
      <include name="com/mycompany/myapp/resource/*"/>
    </adjust>

The map Element

The map element is an immediate optional child of the rename element. It can be used to specify the mapping for the renaming process directly. This is an advanced topic.

Child Elements

  • package
  • class
  • method
  • field

All of these elements use the name attribute to specify the specific element. The method and field element need the class attribute in order to function properly. Neither wildcards nor nested patternset elements are allowed. Use the map attribute to specify the new name (subpackage, classname, methodname and fieldname respectively).
Some examples:

    <map>
      <package name="com" map="etc"/>
      <package name="com.mycompany" map="nocompany"/>
      <package name="com.mycompany.myapp" map="asdf"/>
      <class name="com.mycompany.myapp.MainApp" map="foo"/>
      <method class="com.mycompany.myapp.MainApp"
        name="void main(java.lang.String[])" map="bar"/>
      <field class="com.mycompany.myapp.MainApp" name="field" map="a"/>
    </map>

In this example the package structure 'com.mycompany.myapp' will be obfuscated to 'etc.nocompany.asdf'. The MainApp class will be called 'foo' and its main method will be remapped to 'bar' (and can therefor not be executed from commandline anymore). The field called 'field' will be renamed to 'a'.

Controlling obfuscation exclusion with annotations

In order to exclude certain elements from obfuscation, it is possible to use annotations in the source code instead of listing those elements in the keep element.

Any annotation class can be used for this, but it must be specified in the annotationClass attribute of the rename element and follow the convention as explained below to work. yGuard contains such an annotation in the distribution package ready for use. The annotation class is com.yworks.util.annotation.Obfuscation and can be found in the yGuard distribution in the lib/ObfuscationAnnotation.jar. Feel free add this attribute definition to your own codebase and possibly adjust the package name to your needs. Here is the source code for it:

Obfuscation.java

package com.yworks.util.annotation;

public @interface Obfuscation {

  boolean exclude() default true;

  boolean applyToMembers() default true;
}

This class is also the default annotation yGuard is looking for when obfuscating.

The convention for annotation classes that yGuard understands as obfuscation controlling annotations requires two attributes:

Attributes

Attribute Description Default value
exclude Specifies whether the annotated element should be excluded from the obfuscation. Note, that when retaining a class, the hierarchy of that class, i.e. the chain of outer class names and the package name, is also retained. true
applyToMembers Specifies whether the child elements of the annotated element, if not otherwise specified, should be excluded from the obfuscation. For example, when annotating a class with exclude = true and this attribute set to true, inner classes, fields and methods of this class will be excluded from obfuscation. Annotating a child element of an element that has this attribute set to true will override the parents annotation configuration. true

Generating Patch Jars

The true power of the map element lies in its use together with the patch element, which itself is a child element of the rename top level element.

Attributes

The yguard element has no attributes.

Child Elements

Using the patch element one can generate jars, that can be used to serve as patches for versions of an application that have already been deployed in obfuscated form. During the main obfuscation run, yGuard produces an xml-logfile, in which the mapping between the unobfuscated and obfuscated names is contained. The patch element is used to declare a set of classes, that need to be patched. During the obfuscation, yGuard will include those files in the obfuscated jars only, that are declared inside this element.
For example:

    <patch>
      <class name="com.mycompany.myapp.MainClass"/>
      <class>
        <patternset>
          <include name="com.mycompany.myapp.bugs.*"/>
        </patternset>
      </class>
    </patch>
    <map logfile="yguardlog.xml"/>

This will only include the MainClass class and all classes that belong to the bugs package in a patch jar. In order to work with the previously delivered obfuscated version, it is important to use the map element to specify the mapping of the elements from the previous run. This can most conveniently be achieved by specifying the log file from the corresponding run in the map's logfile attribute.

Complete Examples

There will be some examples given, that represent common use cases.

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

Following are the contents of a complete build.xml file. Just copy the following lines to a new document named build.xml, put the file into your project's root directory and edit the file to suit your needs.

  <?xml version="1.0" encoding="UTF-8"?>
  <!-- file build.xml in your project root directory -->
  <!-- Ant build script for yfiles -->
  <!-- The java based Ant tool is available from -->
  <!-- http://jakarta.apache.org/ant -->
  <!-- This file demonstrates the use of the yGuard byte -->
  <!-- code obfuscator from yWorks Gmbh -->
  <!-- yGuard can be downloaded from -->
  <!--- http://www.yworks.com/products/yguard -->

  <project name="project" default="yguard" basedir=".">

    <!-- edit the following lines to your needs -->
    <target name="init">
    <property name="project_name" value="DemoProject"/>
    <property name="srcDir" value="."/>
    <property name="classDir" value="classes"/>
    <property name="jar" value="${project_name}.jar"/>
    <property name="obfjar" value="${project_name}_obf.jar"/>
    <property name="renamelog" value="${project_name}_renamelog.xml"/>
    <property name="shrinklog" value="${project_name}_shrinklog.xml"/>
    <property name="mainclass" value="com.mycompany.myapp.Main"/>
    <mkdir dir="${classDir}" />
    </target>


    <target depends="jar" name="yguard">
      <taskdef name="yguard" classname="com.yworks.yguard.YGuardTask"
      classpath="yguard.jar"/>
      <!-- the following can be adjusted to your needs -->
      <yguard>

        <inoutpair in="${jar}" out="${obfjar}"/>

        <shrink logfile="${shrinklog}">

          <keep>
            <class classes="protected"
            methods="protected" fields="protected">
              <patternset>
                <include name="com.mycompany.publicapi.**.*"/>
                <exclude name="com.mycompany.publicapi.private.*"/>
                <include name="com.mycompany.menu.reflection.**.*"/>
              </patternset>
            </class>
          </keep>
        </shrink>

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

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

      </yguard>

    </target>

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

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

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

    <!-- removes all that has been built -->
    <target name="clean" depends="init">
      <delete dir="${classDir}" includeEmptyDirs="true" />
    </target>
  </project>

  <!-- end file build.xml -->

Example 2: A Public API

An alternative yguard section could look like this:

  <yguard>

    <inoutpair in="classes.jar" out="classes_obf.jar"/>
    <inoutpair in="utils.jar" out="utils_obf.jar"/>

    <!-- don't let the obfuscator remove the "Deprecated" -->
    <!-- attributes from the .class file entries -->
    <attribute name="Deprecated"/>

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

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

  </yguard>

This case is especially useful when you want to provide and expose a public API. All the classes, methods and fields, that can be seen in a javadoc generated API will be excluded from the shrinking and renaming tasks. Package friendly and private classes, methods and fields will be shrinked or obfuscated whenever possible.
This example also displays the use of the "attribute" element. In this case it prevents the yguard task from removing the "Deprecated" flag from the entities in the .class files.

Example 3: A Demo Program

  <yguard>

    <inoutpair in="demo.jar" out="demo_obf.jar"/>

    <shrink logfile="shrinklog.xml">

      <keep>

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

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

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

      <property name="language-conformity" value="illegal"/>
      <property name="naming-scheme" value="mix"/>
      <keep>
        <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>
        <method name="void readObject(java.io.ObjectInputStream)">
          <patternset refid="datapatternset"/>
        </method>
        <field name="serialVersionUID">
          <patternset refid="datapatternset"/>
        </field>
      </keep>
    </rename>

  </yguard>

This example demonstrates the common use case of a demo program. The keep sections of both the shrink and rename elements contain code entities that will often have to be excluded from the shrinking and renaming process. These are the main code entrypoints (the main method), classes that are loaded per reflection and fields and methods needed for serialization. Note how the same patternsets can be reused using the id and refid attributes.

Example 4: A Program Using an External Library


  <yguard>

    <inoutpair in="mydemo.jar" out="mydemo_obf.jar"/>

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

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

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

  </yguard>

This example demonstrates full method and field obfuscation for a program, that has external dependencies. The dependencies are specified in the externalclasses element using standard Ant path specification mechanisms. Classes residing in lib/external.jar and underneath the lib/additional/classes/ directory (note the trailing slash), will be used to resolve external dependencies during the obfuscation run. This is necessary if external classes want to access obfuscated classes directly using an externally defined interface or superclass. yGuard automatically detects externally declared methods and prevents renaming and shrinking of these items. As a result, the shrinked and obfuscated jar file can be used together with unmodified versions of external libraries without causing any problems.
This example also demonstrates the use of the error-checking property. In this case the Ant target fails if any problem is detected during the obfuscation run.

Example 5: A Program with .properties Files and Other Resource Files


  <yguard>

    <inoutpair in="myapp.jar" out="myapp_obf.jar"/>

    <shrink logfile="shrinklog.xml">
      <keep>
        <!-- single entrypoint: main method -->
        <method name="void main(java.lang.String[])" class="com.mycompany.myapp.Main" />
      </keep>
    </shrink>

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

      <adjust replaceContent="true">
        <!-- plain-text class names in the config files will -->
        <!-- be replaced with the obfuscated name versions -->
        <include name="**/*.config"/>
        <include name="com/mycompany/myapp/init/Main.properties"/>
      </adjust>
      <adjust replacePath="false">
        <!-- keep the complete path to the resources, (gifs...) even if -->
        <!-- package com.mycompany.myapp gets obfuscated by name -->
        <include name="com/mycompany/myapp/resources/*"/>
      </adjust>
      <adjust replaceName="true">
        <!-- Replace the .properties files' names with the obfuscated -->
        <!-- versions if the corresponding .class files get obfuscated -->
        <include name="**/*.properties"/>
        </adjust>
    </rename>

  </yguard>

This example, too, demonstrates full method and field obfuscation for a program, that uses .properties files and other resources files. Some configuration files are used that contain fully qualified classnames for plugins that are going to be obfuscated. Therefore yGuard is instructed to automatically replace the plain-text entries in those files with the obfuscated name versions.
Additionally some resources are hardcoded into the classes (image locations and html files, e.g.). yGuard gets instructed not to move these resource files even if they reside in a package structure that is obfuscated.
Since the property files have been created with the same name as the classes that make use of them and they are being loaded using this.getClass().getName(), yGuard is configured to rename the .properties files according to the obfuscated names of the corresponding .class files.

Example 6: A Program Linked Against a Library That Needs to be Obfuscated


  <yguard>

    <inoutpair in="myapp.jar" out="myapp_obf.jar"/>
    <inoutpair in="lib/thirdpartylib.jar" out="lib/thirdpartylib_obf.jar"/>

    <externalclasses>
      <pathelement location="lib/external.jar"/>
    </externalclasses>

    <!-- Keep all of the attributes for debugging, e.g. -->
    <attribute name="Deprecated, SourceFile, LineNumberTable, LocalVariableTable>
      <patternset refid="myopenapp"/>
    </attribute>

    <rename mainclass="org.myorg.myapp.Main" logfile="renamelog.xml">

      <property name="error-checking" value="pedantic"/>

      <keep>
      <!-- Tell the obfuscator to only adjust my classes -->
      <!-- to work with the obfuscated 3rd party library -->
      <!-- but leave them virtually unmodified otherwise -->
      <!-- The libconnector package however will be -->
      <!-- obfuscated as much as possible -->
      <class classes="private" methods="private" fields="private">
        <patternset id="myopenapp">
          <include name="org.myorg.myapp.**"/>
          <exclude name="org.myorg.myapp.mylibconnector.**"/>
        </patternset>
      </class>

      </keep>
    </rename>

  </yguard>

This example demonstrates almost no method, class, and field obfuscation for a program, that has external dependencies and additionally depends on a third party library jar which has to be obfuscated before deployment. Only those parts that actually interface with the third party jar in the mylibconnector package are being obfuscated. Nothing in the third party library jar will be exposed in the final application, everything will be obfuscated and the code in the open application that makes use of the third party jar will be adjusted. Note that the public part of the application will still be debuggable since all of the crucial attributes will be exposed for the open application part.
The dependencies are specified in the externalclasses element using standard Ant path specification mechanisms. Classes residing in lib/external.jar will be used to resolve external dependencies during the obfuscation run. This is not strictly necessary in this case since the public API will be fully exposed, i.e. no methods which have been declared by interfaces or super class in external classes will be renamed.

Example 7: Using the extends and implements Attributes (Serializable Exclusion)


  <yguard>

    <inoutpair in="myapp.jar" out="myapp_obf.jar"/>

    <shrink>
      <keep>
        <!-- main method -->
        <method name="void main(java.lang.String[])" class="org.myorg.myapp.Main" />
        <!-- serializable classes -->
        <class implements="java.io.Serializable" classes="private" methods="private" fields="private" />
        <!-- menu items loaded per reflection -->
        <class extends="org.myorg.myapp.MyMenuItem" classes="friendly" methods="public" fields="public" />
      </keep>
    </shrink>

    <rename mainclass="org.myorg.myapp.Main" logfile="renamelog.xml">

      <keep>
        <method name="void readObject(java.io.ObjectInputStream)" />
        <method name="void writeObject(java.io.ObjectOutputStream)" />
        <field name="serialVersionUID" />
        <class extends="org.myorg.myapp.MyMenuItem" classes="friendly" methods="public" fields="public" />
      </keep>
    </rename>

  </yguard>

This example demonstrates the usage of the new implements and extends attributes of the class element. All Serializable classes are excluded from shrinking by using the implements attribute of the class element. Additionally, all classes that extend the base class for menu items, org.myorg.myapp.MyMenuItem, are defined as entrypoints for the shrinking engine using the extends attribute of the class element. The readObject and writeObject methods and the field serialVersionUID needed for serialization are excluded from name obfuscation as well.

Example 8: Annotations in Source Code to Control Obfuscation Exclusion

This section gives examples on how to use annotations to control which elements should be excluded from the obfuscation process (i.e., keep their names). The following assumes that there is an annotation class named com.yworks.util.annotation.Obfuscation in the classpath that follows the convention as described above.

Example 8.a: Obfuscation Exclusion per Item

@com.yworks.util.annotation.Obfuscation( exclude = true, applyToMembers = false)
public class Person {

  public String name;

  public String occupation;

  @com.yworks.util.annotation.Obfuscation( exclude = true )
  public int age;
}

Obfuscation

Element Obfuscated?
class Person No
field name Yes
field occupation Yes
field age No

The table above shows the result of the obfuscation of this example. The Person class is annotated to be excluded from the obfuscation, but the applyToMembers attribute is set to false, which means that the child elements of the class (the String and int fields) do not inherit this setting from its parent. The name and occupation fields are not annotated and do not inherit the annotation configuration from their parent, so they are obfuscated. The age field however is also annotated to be excluded from obfuscation and thus keeps its name.

Example 8.b: Obfuscation Exclusion for Members Using applyToMembers

@com.yworks.util.annotation.Obfuscation( exclude = true, applyToMembers = true)
public class Person {

  @com.yworks.util.annotation.Obfuscation( exclude = false )
  public String name;

  public String occupation;

  public int age;
}

Obfuscation

Element Obfuscated?
class Person No
field name Yes
field occupation No
field age No

Again, the class Person keeps its name, but the configuration is inherited by its members, too. The fields occupation and age have no annotation set and inherit the configuration of its parent, which is exclude = true, so they keep their names. The field name however specifies its own annotation and thus overrides the configuration of its parent and sets its own exclusion to false, so it is obfuscated.

Example 8.c: Obfuscation Exclusion for Members using applyToMembers in the Case of Nested Classes

@Obfuscation ( exclude = true, applyToMembers = true )
public class Person {

  public String name;

  public String occupation;

  public int age;

  @Obfuscation ( exclude = false, applyToMembers = true )
  class BirthInfo {

    String birthPlace;

    class Date {

      int year;

      int month;

      int day;
    }
  }
}

Obfuscation

Element Obfuscated?
class Person No
field name No
field occupation No
field age No
class BirthInfo Yes
field birthPlace Yes
class Date Yes
field year Yes
field month Yes
field day Yes

The applyToMembers configuration is also applicable to inner classes: In the above example, the top level class Person is annotated so that itself and all its members should be excluded from obfuscation. But, the inner class BirthInfo overrides this configuration by setting exclude to false for itself and all of its members. When yGuard has to decide whether to keep or obfuscate a non-annotated element, then it will look for annotations by going up the nesting-hierarchy until the top level class is reached or a parent has the applyToMembers configuration set to true. In this case, when deciding whether to keep the inner class Date, yGuard goes up the hierarchy and finds the annotation at BirthInfo, which is annotated exclude = false. This results in Date being obfuscated. The same applies to the members of Date.

Example 8.d: Obfuscation Exclusion Using applyToMembers in the Case of Nested Classes II

@Obfuscation ( exclude = true, applyToMembers = true )
public class Person {

  public String name;

  public String occupation;

  public int age;

  @Obfuscation ( exclude = false, applyToMembers = false )
  class BirthInfo {

    String birthPlace;

    class Date {

      int year;

      int month;

      int day;
    }
  }
}

Obfuscation

Element Obfuscated?
class Person No
field name No
field occupation No
field age No
class BirthInfo No
field birthPlace No
class Date No
field year No
field month No
field day No

The above example shows almost the same code as in Example 8.c, but this time the class BirthInfo has the applyToMembers annotation set to false. One might expect that, as a result, all members of BirthInfo are kept and only BirthInfo is obfuscated, but instead, all elements in this example are kept. The explanation: when reaching Date, yGuard is looking up its parent's configuration, BirthInfo, which has applyToMembers = false. yGuard then proceeds to the next parent class in the nesting-hierarchy, Person, which has applyToMembers = true and exclude = true set. This causes Date to be kept. But keeping a class also means that its fully qualified name and thus its nesting-hierarchy needs to be kept. Although the annotation of BirthInfo does not explicitly retain the the name of the class, the retention of Date and its nesting-hierarchy causes BirthInfo to be kept.

Example 8.e: Default Behavior

public class Person {

  public String name;

  public String occupation;

  @com.yworks.util.annotation.Obfuscation
  public int age;

}

Obfuscation

Element Obfuscated?
class Person Yes
field name Yes
field occupation Yes
field age No

This example shows the default behavior of yGuard without specifying an annotation and when not assigning the attributes of the annotation. Person, name and occupation are obfuscated, while age is annotated. The default value for exclude is true, so the field age is not obfuscated.

Deobfuscating Stacktraces Etc.

yGuard provides a simple tool that makes it easy for the obfuscating party to deobfuscate stacktraces which have been obfuscated using yGuard. During the obfuscation yGuard produces an xml logfile which can automatically be gzipped for convenient storage. You should always keep those logfiles in order to be able to deobfuscate fully qualified classnames or methods or fields for debugging purposes e.g.
In order to run the yGuard deobfuscation tool do the following:

      Console> java -jar yguard.jar mylogfile.xml
A tiny GUI will popup that will enable you to easily deobfuscate stacktraces and fully qualified classnames as well as provide a convenient way to browse the mapping generated by yGuard.
In the main window a tree view displays the package, class, and classmember hierarchy using the unobfuscated names. For each entry that has been obfuscated (classes, packages, methods, and fields that have not been obfuscated at all may not always be shown in the tree) the corresponding mapped/obfuscated name is displayed.
The two buttons at the top of the window allow to change the sorting of the items in the tree structure, so that they are either sorted according to their names before or after the obfuscation. Items will always be sorted by type first: packages, classes, innerclasses, methods, and fields. Small icons provide a convenient way to quickly find the corresponding items.

The lower part of the window contains an editable text area that can be used to enter text or paste stacktraces in. Pressing the button at the bottom of the window labelled "Deobfuscate" will trigger the deobfuscation of the contents in the text area. The tool will try to identify fully qualified class names (separated by dots) and use the mapping information to reconstruct the original names. If the tool identifies a stack trace element, it will try to deobfuscate scrambled line numbers, too, if they have been scrambled during the obfuscation process.

Problems and Bug Reports

If you experience any problems or think you have found a bug feel free to send an email to yguard@yworks.com but please make sure you have read the documentation thoroughly before. We will do our best and try to answer your questions.

DTD used for Ant <yguard>

The obfuscation and shrinking process can be completely configured inside your Ant script. The yguard task and nested elements should be used according to the following DTD. Note that this is for information purposes only, i.e. you do not have to include the following lines anywhere. This DTD should just provide a quick overview of the yGuard syntax. Due to restrictions of the DTD specification, the given DTD does not describe all available yGuard options. Please browse through the documentation above for complete documentation of the yGuard Ant task elements.

  <!ELEMENT yguard (inoutpair+,externalclasses?,attribute*,(shrink|rename)+)>

  <!ELEMENT inoutpair EMPTY>
  <!ATTLIST inoutpair
  in CDATA #REQUIRED
  out CDATA #REQUIRED
  resources CDATA #IMPLIED>
  <!--
  NOTE: the resources attribute only has an effect if a shrink element is present inside the yguard element.
  -->

  <!ELEMENT externalclasses ANY>
  <!-- the externalclasses element is used just like Ant's classpath
  element. See the Ant documentation for further details-->

  <!ELEMENT attribute (patternset)*>
  name CDATA #REQUIRED>

  <!ELEMENT shrink (entrypointjar*,keep?)>
  <!ATTLIST shrink
  logfile CDATA #IMPLIED
  createStubs CDATA #IMPLIED>

  <!ELEMENT entrypointjar>
  <!ATTLIST entrypointjar
  name CDATA #REQUIRED>

  <!ELEMENT rename (property*,patch?,adjust*,map?,keep?)>
  <!ATTLIST rename
  mainclass CDATA #IMPLIED
  logfile CDATA #IMPLIED
  conservemanifest CDATA #IMPLIED
  replaceClassNameStrings CDATA #IMPLIED>

  <!ELEMENT property EMPTY>
  <!ATTLIST property
  name CDATA #REQUIRED
  value CDATA #REQUIRED>

  <!ELEMENT patch (class)*>

  <!ELEMENT adjust (#PCDATA)>
  <!ATTLIST adjust
  replaceName CDATA #REQUIRED
  replaceContent CDATA #REQUIRED
  replacePath CDATA #REQUIRED>

  <!ELEMENT map (class|method|field|package)*>

  <!ELEMENT package (patternset)*>
  <!ATTLIST package
  name CDATA #REQUIRED
  map CDATA #REQUIRED>
  <!--
  NOTE: the map attribute is only supported
  if the <package> element is nested inside a <map> element, whereas the patternset is
  only supported inside the <keep>/<expose> sections.
  -->

  <!ELEMENT keep (package|class|method|field|sourcefile|linenumbertable)*>
  <!--
  NOTE: the nested <package>,<sourcefile>,<linenumbertable> and <attribute> sections are only
  supported in the <rename> element.
  -->
  <!ATTLIST keep
  linenumbertable CDATA #IMPLIED
  localvariabletable CDATA #IMPLIED
  localvariabletypetable CDATA #IMPLIED
  runtimeinvisibleannotations CDATA #IMPLIED
  runtimeinvisibletypeannotations CDATA #IMPLIED
  runtimevisibleannotations CDATA #IMPLIED
  runtimevisibletypeannotations CDATA #IMPLIED
  sourcefile CDATA #IMPLIED>

  <!ELEMENT class (patternset)*>
  <!ATTLIST class
  classes CDATA #IMPLIED
  fields CDATA #IMPLIED
  map CDATA #IMPLIED
  methods CDATA #IMPLIED
  name CDATA #IMPLIED>
  <!--
  NOTE: the map attribute is only supported
  if the <class> element is nested inside an <rename> element.
  -->

  <!ELEMENT method (patternset)*>
  <!ATTLIST method
  class CDATA #IMPLIED
  map CDATA #IMPLIED
  name CDATA #IMPLIED>
  <!--
  NOTE: the map attribute is only supported
  if the <method> element is nested inside an <rename> element.
  -->

  <!ELEMENT field (patternset)*>
  <!ATTLIST field
  class CDATA #IMPLIED
  map CDATA #IMPLIED
  name CDATA #IMPLIED>
  <!--
  NOTE: the field attribute is only supported
  if the <method> element is nested inside an <rename> element.
  -->

Attention users of IDEs that "support" the creation of Ant files (e.g. IDEA's IntelliJ): Your IDE may indicate some errors inside your ANT file when you use yGuard specific elements. This is because the IDE does not know about the DTD used by yGuard. However this is not a real problem, since the Ant file should nevertheless work as expected.


Copyright © 2002-2014 yWorks. All Rights Reserved.