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:
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:
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.
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.
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:
The programmer can specify explicit replacement names using 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().
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.
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.
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.