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

Important: The syntax described here is deprecated.
Documentation for the current Ant syntax of the successor yGuard releases is available here.

yGuard 1.5 Ant Task Documentation

Contents

Installation

In order to make use of yGuard's obfuscate 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):

<taskdef name="obfuscate" 
         classname="com.yworks.yguard.ObfuscatorTask" 
         classpath="yguard.jar"/>

<target name="obfuscate">
  <obfuscate>
    <!-- modify obfuscate element attributes and 
         insert your statements here -->
  </obfuscate>
</target>

Alternatively, you can place the taskdef element inside the target that uses the obfuscate task:

<target name="obfuscate">
  <taskdef name="obfuscate" 
           classname="com.yworks.yguard.ObfuscatorTask" 
           classpath="yguard.jar"/>
  <obfuscate>
    <!-- modify obfuscate element attributes and 
         insert your statements here -->
  </obfuscate>
</target>

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

DTD used for Ant <obfuscate>

The obfuscation process can completely be configured inside your Ant script. The following DTD should be used in it (please note that this is for information purposes only, i.e. you do not have to include the following lines anywhere):

<!ELEMENT obfuscate (inoutpair+,externalclasses?,
                     property*,patch?,expose?,map?,adjust*)>
<!ATTLIST obfuscate
    mainclass CDATA #IMPLIED
    logfile CDATA #IMPLIED
    conservemanifest CDATA #IMPLIED
    replaceClassNameStrings CDATA #IMPLIED
>

<!ELEMENT inoutpair EMPTY>
<!ATTLIST inoutpair
    in CDATA #REQUIRED
    out CDATA #REQUIRED
>


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

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

<!ELEMENT patch (class)*>

<!ELEMENT expose (class|method|field|sourcefile|attribute|linenumbertable)*>
<!ATTLIST expose
    linenumbertable CDATA #IMPLIED
    localvariabletable CDATA #IMPLIED
    sourcefile CDATA #IMPLIED
    localvariabletypetable CDATA #IMPLIED
    runtimevisibleannotations CDATA #IMPLIED
    runtimevisibletypeannotations CDATA #IMPLIED
    runtimeinvisibleannotations CDATA #IMPLIED
    runtimeinvisibletypeannotations CDATA #IMPLIED
>

<!ELEMENT class (patternset)*>
<!ATTLIST class
    classes CDATA #IMPLIED
    methods CDATA #IMPLIED
    fields CDATA #IMPLIED
    name CDATA #REQUIRED
    map CDATA #IMPLIED
>

<!ELEMENT method (patternset)*>
<!ATTLIST method
    class CDATA #IMPLIED
    name CDATA #REQUIRED
    map CDATA #IMPLIED
>

<!ELEMENT field (patternset)*>
<!ATTLIST field
    class CDATA #IMPLIED
    name CDATA #REQUIRED
    map CDATA #IMPLIED
>

<!ELEMENT sourcefile (property*,patternset*)>

<!ELEMENT linenumbertable (property*,patternset*)>

<!ELEMENT attribute (patternset*)>


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

<!ATTLIST adjust
    replaceName CDATA #IMPLIED
    replaceContent CDATA #IMPLIED
    replacePath CDATA #IMPLIED
>

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

<!ELEMENT package EMPTY>
<!ATTLIST package
    name CDATA #REQUIRED
    map CDATA #REQUIRED
>

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.

The basic idea is, that all elements will be obfuscated by this task. You have to specify all classes, methods, fields, and attributes that should be exposed, i.e. that will not be obfuscated but kept in the API. There are different use cases, where you sometimes want to expose or simply just have to expose some elements. See the General Hints and Complete Examples sections at the end of this text for more information. Exposing elements can be achieved by using both the expose element and the mainclass attribute of the obfuscate element.

The obfuscate Element

The following attributes can be specified in the obfuscate element.

The inoutpair Elements

At least one inoutpair element has to be specified in order to run the obfuscation task. This elements specifies the jar files, that contain the class files, that should be obfuscated and the name of the jar file, that will be created during the obfuscation process. Note that only class files will be used for obfuscation, other files (resources, ...) will be simply copied from the source jar to the target jar.
This element has two mandatory attributes:

The externalclasses Element

If the jar to be obfuscated depends on external classes or libraries, this element can be used to specify classpaths to these entities. These libraries will neither be modified nor obfuscated. Use the inoutpair element for this purpose! See the examples later in this document for an example of when to use this element.
The elements attributes and child elements can be seen on the Ant documentation page about using path elements.

The property Elements

property elements can be used to give hints to the obfuscation engine. Depending on the exact version of yGuard, the task may use these hints to control the process of obfuscation.
This element has two mandatory attributes:

As of yGuard version 1.5, the following attributes are supported:

The expose Element

This element is a child of the obfuscate element. It can be used to specify elements, that are exposed to the outside world. These can be classes, methods, fields, and attributes.

The ObfuscatorTask can be used to remove a lot of unnecessery information from class files, that are to be distributed and should not be decompiled. There are a number of different boolean attributes one can specify to control what information should be exposed (i.e. not be obfuscated or removed) by this task.
This will affect all class files. For a better control of which attributes should be exposed or removed from what classes use the attribute Element.

The class Element

The class element can be used to expose classes to the public, i.e. to exclude their names and/or their methods and fiels from the obfuscation process, so that they remain unchanged.

There are two attributes, which determine what to do with the methods and fields of the specified class:

The methods, fields and classes (see the following paragraphs) determine what elements get exposed during obfuscation. The following table lists the possible values for all of these attributes and shows which elements will be exposed. A '*' denotes, that elements, which have the given visibility will be exposed, for the specified attribute value. A '-' denotes, that the obfuscator tries to obfuscate these elements.

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

There are three possible ways of specifying classes.

  1. One can specify a 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 expose 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 exposing a complete public API. 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 expose 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 exposed, i.e. left unobfuscated. This element has two attributes:

Some 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 expose the main method of the MyClass class and the foo method. Additionally all readObject and writeObject methods (used for Serialization) will be exposed 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 exposed, i.e. left unobfuscated. This element has two attributes:

Some examples:

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

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

The attribute Element

Using the attribute element you can specify for which classes the which attributes should be exposed, i.e. left unobfuscated. This element has only one attribute:

An example:

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

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

The sourcefile Element

Using the sourcefile element you can specify for which classes the sourcefile attribute (used in stacktraces, e.g.) should be exposed, i.e. left unobfuscated. Although roughly the same can be achieved using the attribute element, this element has no attributes but allows for nested property elements that can be used to hint the obfuscation engine what to do with the source file names.

Some examples:

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

This will expose source file names of all the classes in the com.mycompany.myapp packages and subpackages. Note that this will prevent proper obfuscation, since the name of the source file is normally strongly coupled with the unobfuscated name of the class (e.g. "MySecretAlgorithm.java". The following example shows how to overcome this.

<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. Note that as of yGuard 1.5 the property "mapping" is the only property currently being supported in the sourcefile element.

The linenumbertable Element

Using the linenumbertable element you can specify for which classes the linenumbertalbe code attribute (used in stacktraces, e.g.) should be exposed, i.e. left unobfuscated. Although roughly the same can be achieved using the attribute element, this element has no attributes but allows for nested property elements that can be used to hint the obfuscation engine what to do with the line number tables.

Some examples:

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

This will expose 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 exposed 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 expose 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 mapping-scheme property can be used with the following two values as of yGuard 1.5:

The adjust Element

Using the adjust element one can specify resource files whose names and/or contents should be adjusted to reflect the obfuscated class names. This element has three attributes:

Some examples:

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

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

<!-- suppress the adjustment of the resource path 
     com/mycompany/myapp/resource. -->
<!-- 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 obfuscate element. It can be used to specify the mapping for the obfuscation process directly. This is an advanced topic.

The element can have for different kinds of child elements.

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

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 obfuscate top level element.

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 and put the file into your project's root directory.

<?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="obfuscate" 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="obfuscationlog" value="${project_name}_obflog.xml.gz"/>
  <property name="mainclass"      value="com.mycompany.myapp.Main"/>
  <mkdir dir="${classDir}" />
</target>


<!-- obfuscate -->
<target depends="jar" name="obfuscate">
  <taskdef name="obfuscate" classname="com.yworks.yguard.ObfuscatorTask" 
           classpath="yguard.jar"/>
  <!-- the following can be adjusted to your needs -->
  <obfuscate mainclass="${mainclass}" logfile="${obfuscationlog}"
             replaceclassnamestrings="true">
  <property name="error-checking" value="pedantic"/>
  <inoutpair in="${jar}" out="${obfjar}"/>
  <expose>
    <class classes="protected" 
           methods="protected" fields="protected">
      <patternset>
        <include name="com.mycompany.publicapi.**.*"/>
        <exclude name="com.mycompany.publicapi.private.*"/>
      </patternset>
    </class>
  </expose>
  </obfuscate>
</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="obfuscate">
  <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 obfuscate section could look like this:

<obfuscate mainclass="com.mycompany.myapp.Main"
           replaceclassnamestrings="true"
           logfile="log.xml.gz">
  <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          -->
  <expose>
    <class classes="protected" 
           methods="protected" 
           fields="protected"/>
    <attribute name="Deprecated"/>
  </expose>
</obfuscate>

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 exposed. Package friendly and private classes, methods and fields will be obfuscated whenever possible.
This example also displays the use of the "attribute" element. In this case it prevents the obfuscator from removing the "Deprecated" flag from the entities in the .class files.

Example 3: A Demo Program

<obfuscate mainclass="com.mycompany.myapp.Main" logfile="log.xml"
           replaceclassnamestrings="true">
  <inoutpair in="demo.jar" out="demo_obf.jar"/>
  <property name="language-conformity" value="illegal"/>
  <property name="naming-scheme" value="mix"/>
  <expose>
    <!-- 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>
  </expose>
</obfuscate>

Example 4: A Program Using an External Library

<obfuscate mainclass="com.mycompany.myapp.Main" logfile="log.xml"
           replaceclassnamestrings="true">
  <inoutpair in="mydemo.jar" out="mydemo_obf.jar"/>
  <property name="error-checking" value="pedantic"/>
  <externalclasses>
    <pathelement location="lib/external.jar"/>
    <pathelement location="lib/additional/classes/"/>
  </externalclasses>
  <expose>
    <class classes="public"/>
  </expose>
</obfuscate>

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 obfuscation of these items. As a result, the obfuscated jar 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

<obfuscate mainclass="com.mycompany.myapp.Main" logfile="log.xml"
           replaceclassnamestrings="true">
  <inoutpair in="myapp.jar" out="myapp_obf.jar"/>
  <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>
</obfuscate>

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

<obfuscate mainclass="org.myorg.myapp.Main" logfile="log.xml.gz"
           replaceclassnamestrings="true">
  <inoutpair in="myapp.jar" out="myapp_obf.jar"/>
  <inoutpair in="lib/thirdpartylib.jar" out="lib/thirdpartylib_obf.jar"/>
  <property name="error-checking" value="pedantic"/>
  <externalclasses>
    <pathelement location="lib/external.jar"/>
  </externalclasses>
  <expose>
    <!-- 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 all of the attributes for debugging, e.g. -->
    <attribute name="Deprecated, SourceFile, LineNumberTable, LocalVariableTable>
      <patternset refid="myopenapp"/>
    </attribute>
  </expose>
</obfuscate>

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.

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, for example.
In order to run the yGuard deobfuscation tool do the following:

Console> java -jar yguard.jar mylogfile.xml.gz

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.

General Hints

There are a couple of things you should be aware of, when obfuscating software. You can find a lot of information on http://www.Retrologic.com. This is the site which hosts 'Retroguard'. The yGuard library has been derived from Retroguard. The most important facts are described here briefly:

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.