JCloaktmOperation

Class Paths

JCloak locates and loads classes from the classpath indicated via class path entries. You can modify the classpath using the project setting dialog's class path settings tab or by editing the project configuration file and modifying the AddToClassPath directives.

Initially JCloak determines the classpath by:

  1. The classpath to the Java 2 VM classes used by JCloak.
  2. The initial classpath specified during running the new project wizard.
  3. Classpath's to any classes JCloak requests from a Locate Class Dialog.

JCloak groups the classes it loads into sets based on the sense of the included and obfuscated modifiers on the class path entry. The modifiers work as follows:

included
JCloak includes the classes in the output class set, the set of classes written to the output Jar, Cab or folder.
obfuscated
Classes on classpaths with the obufscated modifier are obfuscated.

The following table summarizes what JCloak does in response to these modifiers:

Include Obfuscate What JCloak Does
false false Classes are only used for reference to determine if methods are safe to obfuscate. JCloak will partially examine these classes only if they are referenced from an obfuscateable class.  These classes are assumed to be immutable (for example the java.* classes). Any references these classes make to the obfuscated classes set will cause the referenced symbol to be automatically blocked from obfuscation.
false true Classes are obfuscated, but are never written to the output class set .  This can be used to support incremental obfuscation, where, for example, an optional library is shipped separately from the main product.
true false All classes found on this classpath are included in the output class set, yet no obfuscation is performed on them.  These classes are treated like reference classes, except that they are included in the output class set .  Use this setting to for the class path to include a thirdparty library in your output jar file without obfuscating the classes in the library. 
true true All classes found on this classpath are loaded and fully obfuscated, unless the remove un-referenced classes option is selected. In that case, only the classes referenced are obfuscated and saved to the output class set .  Individual classes or packages can be marked as dynamically loaded (via forName()) in which case they are treated as referenced and saved to the output class set as well.

 Note JCloak assumes that any class found on a classpath that is not marked obfuscate never directly references any other class on a classpath that is marked obfuscate. Indirect or virtual references are allowed; for example if Mutable is an interface on a classpath that is not marked obfuscate and Window is a class found on a classpath this is marked obfuscate it is permissible for a class Referrer to reference the Window via the Mutable interface but not permissible for Referrer to reference a Window method directly.

Controlling Obfuscated Names

During obfuscation, JCloak changes package names, class names, and symbol names, reducing their size and making them nonspecific. These obfuscating names are usually chosen at random.  The user, however, may influence renaming by various means.

Controlling Symbol Renaming

When the global switch, "Obfuscate Methods and Fields" is set (see the Obfuscate Settings tab in the Graphical User Interface or the ObfuscateSymbols directive in the Command Line Interface), JCloak will obfuscate symbol names.

When considering which symbols are eligible for obfuscation, JCloak uses a constructive model. The program assumes that it can safely obfuscate any symbol that can not be referenced from outside of the program (that is the symbol can not be referenced by any classes in the the reference class set).

JCloak provides extensive mechanisms to control whether symbols are obfuscated and, if so, how obfuscated symbol names are chosen.

The user can specify exclusion of methods or fields by one of the following methods in no particular order:

  1. The main() method is excluded in the class specified as the main class.  The  MainClass directive does this
  2. The obfuscate access level setting. This is set globally via the project setting dialog's obfuscate settings tab or on a class or package level using the class settings or package properties.
  3. The symbol's access level is less restrictive than the symbol obfuscation access level set globally. This is specified using the SymbolAccessLevel directive in Command Line or using the equivalent "Project Settings Dialog" Obfuscate Settings tab in the GUI.

The programmer can specify explicit replacement names using a "name map" file.

From a Name Map File

You may also specify that JCloak should read an input "name map" file and/or save an output "name map" file.  This file is formatted just like a Java properties file, that is, it contains pairs of names matching one of the following two forms:

A: <fully-qualified-class-name> = <obfuscatedClassName>
B: <fully-qualified-class-name>.<symbolSignature> = <obfuscatedSymbolName>

JCloak will use the translations in the name map that are of form B to obfuscate the symbol indicated by the signature and fully qualified class name to the obfuscated symbol name specified.

The symbol name map need not specify all of the symbols in the class file and may contain names that are not in the class file. If JCloak is unable to find a mapping for a symbol name it will generated a random unique obfuscated name for the symbol that does not match any other obfuscated name in the map or conflict with existing names in the classes.

Note that JCloak performs limited validation on the names specified in an input symbol map. If you edit it to specify two different obfuscated names for methods that were in an inheritance override relationship, JCloak will report an error like the following:

'Attempt to ofuscate foo()V in com.acme.Bar but is already obfuscated to c'

This error indicates method Bar.foo overloaded a method that specified 'c' as the obfuscated name, but the name map specified a different name for Bar.foo().

Controlling Class Renaming

Overview

Class and package names are normally obfuscated together by JCloak, thus flattening the package structure. This provides the maximum obfuscation making it difficult to determine any logical association between classes. You may optionally chose to preserve package names, but obfuscate the classes names within the package. The section on Class Name Obfuscation Settings in the GUI, and the description of  the ObfuscateClassNames directive in the command line section both will describe how to control class and package obfuscation.

JCloak tests the following criteria, in the indicated order, to determine if a class may have it's class and or package name obfuscated.  If any of the criteria is true the classes name will not be obfuscated.

  1. If the class is a Java bean or argument or return type for a Java bean method and the Java bean settings indicate the class should be preserved as a Bean.
  2. If the class is the main() class, defined by the MainClass directive.
  3. If the class matches an explicit exclude (see the Command Line directive ExcludeClassNameObfuscate)
  4. If the class derives from a class that is named by an ExcludeDerivedFromClass directive.
  5. If the class implements an interface that is named by an ExcludeImplementsInterface directive.
  6. If the class is declared with an access modifier less restrictive then the global, per-class or per-package Class Access Level setting. The section on Class Name Obfuscation Settings describes how to alter the Class Access Level setting.

JCloak iterates through any of the classes in all the packages and generates a set of random names of the form 'Cn'.   If a name map is loaded, JCloak will use the translations in the name map that are of form A to set the obfuscated class name as specified in the map entry.  Note that it is possible when editing the name map to alter package structure!  JCloak does not check or guard against this-use caution when maping class names!

If any class name is blocked from obfuscation or has it's obfuscated name set via a class name map then the package name for all other classes in the same package are also blocked from obfuscation. This prevents an intra-package reference from unintended promotion to an inter-package reference.

Scanning Class References

If unreferenced class removal is specified JCloak will only load classes it determines are referenced

The starting class[es] for determining what is referenced will be the set of 'Externally Referenced' classes.  The programmer specifies to JCloak the classes that are 'Externally Referenced' classes.

JCloak loads and scans all the classes in the specified set of externally referenced classes then recursively loads and scans all classes they reference.

For an application the class indicated as the main class (using the MainClass directive) is by default the only 'Externally Referenced' class. JCloak will scan this class and load the complete set of classes referenced from it. You specify a MainClass from the initial project create wizard.

For an Applet, the project create wizard sets JCloak to preserve the "Applet derived classes" class name using the ClassSettings directive.  JCloak automatically preserves the methods from java.applet.Applet that the Applet overrides.

In general a class is deemed externally referenced if it's class name is preserved via any of the exclude criteria defined in the Controlling Class Renaming section.