Command Line

.

Overview

JCloak enables the user to run the entire obfuscation process in a Makefile or batch-file via the "command line" option. A JCloak project configuration file controls the obfuscation process. The GUI can be used to generate the project configuration file for your application or you may create it using a text editor.

To load and run a saved project configuration file in a batch file or shell script use JCloak -cfg <file>, where <file> is the path to the configuration file. Paths within the configuration file are always saved relative to the configuration file location. The paths are saved in an operating system neutral format. Note: with no command line arguments specified, JCloak will automatically start the GUI.

The command line arguments are listed in the table below

.

.

.

.

Project Configuration File

The Project configuration file is specified via the -cfg switch on the JCloak command line. The configuration file is a text file containing a series of keywords and their arguments. Java style comments may be included. Comments and white space are ignored.

The general form of a configuration command is, keyword(arg0, arg1, ... argn).The following sections list the keywords and their functions.

wildcard expressions

Some JCloak configuration file command arguments may be wildcarded by simple expressions. A simple wildcard is restricted by one of three allowed forms.

*

- match any string.

*<ends-with>

- match any string ending with the string <ends-with>

<starts-with>*

- match any string starting with the string <starts-with>

Note that for package names, a wildcard postfix only includes package members at the same level. This is according to the operation of the java importdirective.

For example, "java.lang.*" will match any class in package java.lang

NOTE Wildcarded expressions in directives are not supported in the GUI.  JCloak will read and process these directives in GUI mode but they are NOT SAVED to the project file.

File path names

Path names in configuration files may be specified with any file separator character. Path names with forward or backward slashes (/,\) are automatically converted to forward slashes (/) on UNIX systems or backward slashes (\) on Windows systems .

Substitution Variables

You can place variables in paths in the configuration file and specify the string value of the variable on the command line. In addition the special variable CLASSPATH, specifies JCloak should match the first entry on the environment classpath (System Property java.class.path).

Substitution variables are delimited by the % character, e.g.. %CLASSPATH%.

For example given the classpath:

/usr/bar/bee.jar:/usr/bar/foo.jar:/usr/local/Java/jre/lib/rt.jar
The directive
AddToClassPath("%CLASSPATH%/foo.jar", true, true)
would be expanded to
AddToClassPath("/usr/bar/foo.jar", true, true) .

The CLASSPATH variable is internally defined. You can also define variables using the '-var' option on the command line. For example; using the JCloak command 'JCloak -var:foo=/usr/local' would substitute /usr/local for the string %foo%. %foo% can appear in any directive that has a file path argument.

Note the variables are case sensitive and paths are automatically normalized to the OS separator character.

Configuration Directives

Obfuscation Control Directives
BeanSettings({PUBLIC | PACKAGE | PRIVATE | NONE })

The 'Java Bean Settings' control sets the global setting for what classes JCloak will recognize as Java Bean's and how JCloak will preserve the bean methods and classes these Bean's define and use.

JCloak can recognize and use BeanInfo classes to automatically exclude classes and methods that a Bean want's to expose publicly. JCloak can also introspect a class to determine the Bean methods and preserve them.

Bean controls can also be set on a per-package or per-class basis. Per class settings override per package settings which override default global settings.

JCloak puts attributes in the manifest of the output Jar file to indicate each Bean.

The following settings and actions are defined:

 
ClassNameAccessLevel({PUBLIC | PACKAGE | PRIVATE | NONE })

The ClassNameAccessLevel determines the global access level setting  for what class names JCloak will exclude from obfuscation.  JCloak will only obfuscate class names with an access level equal to, or more restrictive than the indicated value, as follows:

The ExcludeMethod()and/or ClassSettings() or PackageSettings() directives may be used to further limit what classes are obfuscated or override these settings.

ClassSettings(<name>, <symbol-access-level>, [class-access-level], [Java-beans-setting], [serialize-setting])

This directive allows you to control obfuscation for the named class (name must be the fully qualified name of the class). The 'symbol-access-level' argument specifies what methods or fields JCloak will obfuscate in the named class.  This access level setting takes precedence over the global access level specified by the SymbolAccessLevel() directive.  The values allowed are shown in the following table:

The 'class-access-levell' argument sets the minimum access this class must have for it to be eligible to have it's name obfuscated. If the classes access modifier is equal or more restrictive then this setting, the classes name will be obfuscated if no other reason blocks the obfuscation. The values allowed are shown in the following table:

The 'Java-beans-setting' argument sets what classes JCloak will recognize as Java Bean's and how JCloak will preserve the bean methods and classes these Bean's define and use.

JCloak can recognize and use BeanInfo classes to automatically exclude classes and methods that a Bean want's to expose publicly. JCloak can also introspect a class to determine the Bean methods and preserve them.

Bean controls can also be set on a per-package or per-class basis. Per class settings override per package settings which override default global settings.

JCloak puts attributes in the manifest of the output Jar file to indicate each Bean.

The following settings and actions are defined:

The 'serialize-setting' argument controls how JCloak handles Serialization for the indicated class. JCloak can be programmed to obfuscate or preserve the class name and non transient field name for the Serializable class.

Settings for this argument override the default setting for handling Serializable classes. The allowed argument values are:

ExcludeClassNameObfuscate(<flags>, <name>)

Excludes any class matching <name> from obfuscation of it's class name, where <name> is the class's fully qualified name or a simple wildcard expression. If any class name is blocked from obfuscation then the package name for all other classes in that class's package is also blocked from obfuscation. This prevents an intra-package reference from unintended promotion to an inter-package reference. <flags> may include the following allowed modifiers for top level classes:

NONE

Match only class with no modifiers (package access)

PUBLIC

Match only public classes

PRIVATE

Match only private classes

ABSTRACT

Match only abstract classes

INTERFACE

Match only interfaces

FINAL

Match only final classes

ALL

Match classes with any of the above modifiers or no modifiers at all

In addition, inner classes <flags> may include the modifiers for members.

PRIVATE

Match only private inner classes.

PROTECTED

Match only protected inner classes

STATIC

Match only static inner classes.

ExcludeDerivedFromClass(<name>)

Excludes any classes from having their class name obfuscated if the class derives from a class matching <name>. The <name> argument must be a fully qualified class name. Wildcards are not allowed.

ExcludeField(<flags>, <className>, <sig>)

Causes any field that matches the indicated <flags> with the field signature <SIG>, and defined by class <className> to be excluded from JCloak operations. The <className> must be the fully qualified name of the class or a simple wildcard expression. Similarly the <SIG> argument must be a field signature or a simple wildcard expression. Refer to Appendix A for the grammar for generating field signatures.

For example:

ExcludeField(PUBLIC, MyPackage.MyClass, "testZ");

will exclude the test field (public boolean test) in the class MyClass in package MyPackage. Note that the quotes (") are needed around the signature.

The <flags> argument may be one or more of the following list of flags-separated by &-indicating the field definition must match the flags specified to be excluded.

NONE

Match only fields with no modifiers (package access)

PUBLIC

Match only public fields

PRIVATE

Match only private fields

PROTECTED

Match only protected fields

STATIC

Match only static fields

FINAL

Match only final fields

ALL

Match fields with any of the above modifiers, or no modifiers at all

 

ExcludeImplementsInterface(<name>)

Excludes any class from having its class name obfuscated if the class implements an interface matching <name>. The <name> argument must be a fully qualified class name. Wildcards are not allowed.

ExcludeMethod(<flags>, <className>, <sig>)

Causes any method that matches the indicated <flags> with the method signature <SIG>, and defined by class <className> to be excluded from JCloak operations. The <className> must be the fully qualified name of the class or a simple wildcard expression. Similarly the <SIG> argument must be a method signature or a simple wildcard expression. Refer to Appendix A for the grammar for generating method signatures.

For example:

ExcludeMethod(PUBLIC & STATIC, MyPackage.MyClass, "main([Ljava/lang/String;)V");

will exclude the main() method (public static void main(String args[])) in the class MyClass in package MyPackage. Note that the quotes (") are needed around the signature.

The <flags> argument may be one or more of the following list of flags-separated by &-indicating the method definition must match the flags specified to be excluded.

NONE

Match only methods with no modifiers (package access)

PUBLIC

Match only public methods

PRIVATE

Match only private methods

PROTECTED

Match only protected methods

STATIC

Match only static methods

FINAL

Match only final methods

SYNCHRONIZED

Match only synchronized methods

ALL

Match methods with any of the above modifiers, or no modifiers at all

LineDebug({true | false})

Set to "true" to preserve the debug line numbers stored with each method. Set to "false" and the line numbers are stripped. The default is false. The debug line numbers can help to locate the source of an exception. If the source file name attribute and debug line numbers are both retained then exception tracebacks will indicate the source file name and line number at which the exception occurred. See also the SourceName keyword.


LocalDebug({true | false})

Set to "true" to preserve the debug local symbols stored with each method. Set to "false" and the local symbols are stripped. The only use for local symbols is for a debugger. The default setting (false: to remove) is recommended.

MainClass(<name>)

Use this keyword to specify the main class, i.e. the Applet derived class or the class defining the main() method.

JCloak builds the set of references starting from the main class. The main class is by definition included in the obfuscated class set. The main class will automatically have it's class name preserved. The main() method, if the main class is an application class, will have it's method name automatically excluded from obfuscation.

ObfuscateClassNames({classandpackage | classonly | neither})

Sets the allowed obfuscation for classes according to the following table.

ObfuscateSymbols({true | false})

Set to "true" to cause symbols to be obfuscated. Set to false to leave symbols unmolested. The default is false. 

PackageResourceSearchSettings(<package-name>, <include-resources>, [sub-dir...])

Include resources (eg. GIF's, JPEG's, properties, etc. see SetResourceFileExtensions() for the default list and how to change it) found in the path for the indicated package.  The path is searched starting from the path to the package and terminating when a path that is part of another package is found.  The search can be restricted to one or more sub-directories relative to the package's path by listing them in the optional 'sub-dir' argument.

The path to the resource is adjusted to match the obfuscated package name. In addition, any '.properties' resources that match a class name are renamed to match the class name.  Note: Properties files that have Locale and Language extensions are renamed properly to allow getBundle() to find them.

Class names passed to getBundle(), getResource(), or getResourceAsStream() or any Strings based on class names passed to these methods must be generated using the .class primitive (this primitive is described in the Java Language Specification Appendix D)       JCloak supports automatic adjustment of the special Class primative.

Example 1

PackageSettings(<package-name>, <symbol-access-level>, [class-access-level])

This directive allows you to control obfuscation for the named package (the name must be the fully qualified name of the package, eg. 'Java.lang'. Don't include a trailing ".*")

The 'symbol-access-level' argument specifies what methods or fields JCloak is permitted to obfuscate in the classes in this package.  This access level setting takes precedence over the global access level specified by the SymbolAccessLevel() directive.  The values allowed are shown in the following table:

The 'class-access-level' argument sets the minimum access this class must have for it to be eligible to have it's name obfuscated. If the classes access modifier is equal or more restrictive then this setting, the classes name will be obfuscated if no other reason blocks the obfuscation. The values allowed are shown in the following table:

 

PreserveSerialized(<preserve-setting>)

This directive controls how JCloak handles Serializeable classes. JCloak can be programmed to obfuscate or preserve the class names and non transient field names for serializable classes.

 

This serialized setting can also be overriden on a per-class basis, see the ClassSettings directive.

The Java serialized form of an object stores the class names and the serializable field names and values. The Java object serialization code uses a stream unique identifiers to identify the version of the class that wrote the object stream. The symbol 'serialVersionUID' must be declared in the class to indicate the stream version the class is compatible with, the default for this value is a hash of the class, field and method names (see the Java Object Serialization Specification for more details). Both the stream format and the stream unique identifier are based on names, thus present a challenge for obfuscation.

There are two ways to handle obfuscation of a class that is serialized:

  1. Obfuscate the class then generate the serialized form.
  2. Preserve names in the class that were stored in the stream and compute the appropriate stream unique identifier.

If you chose the first method you must use the LoadNameMap and SaveNameMap to ensure the symbol names are the same for all compatible classes. To use the second method set PreserveSerialized to 'preserve'

PrintableNames({true | false})

Set to "true" to cause symbols names to be printable (in the Unicode C0/C1 set of Alpha characters). Set to "false" for maximum obfuscation. Note, the Java 2 and Netscape class verifiers will not tolerate non PrintableNames.

RemoveUnreferencedSymbols({true | false})

This directive is useful for reducing the download size of Applet's.  When remove unreferenced symbols is enabled JCloak will scan the set of all references starting from the Applet derived class and note any method or field that is unreferenced.  The symbol and associated byte code (for a method or initialized field) are removed and not saved with the obfuscated class.

In addition JCloak removes symbols that are simply unused by products of the compilation process, this includes constant symbols resolved at compile time.

Note that JCloak actually scan's references from any and all classes that are determined to be Externally Referenced. See the section on Scanning Class References for an overview of how JCloak determines the classes references.

RemoveUnreferencedClasses({true | false})

This directive is useful for reducing the download size of Applet's, especially in conjunction with  RemoveUnreferencedSymbols  When remove unreferenced classes is enabled JCloak will scan the set of all references starting from the Applet derived class and note any class that is unreferenced.  The classes that are not referenced are not saved with the obfuscated classes.

SetResourceFileExtensions(<ext...>)

Specify the list of valid file extensions for resources. The default list is: "properties", "gif", "jpeg", "jpg", "au", "mid", "wav", "aiff", "rmf", "css", "html", "htm".  Specify the extensions without the leading dot (.).

If you specify an empty list (eg. SetResourceFileExtensions()) JCloak will not include any resources with your obfuscated output.

Example :

SetResourceFileExtensions("gif", "jpeg") will only load .gif files or .jpeg files.
SetObfuscatedClassNamePrefix(<prefix-string>)

Specify an extension (other than "C") for JCloak to prefix all obfuscated class names with. JCloak will generate obfuscated names of the form 'number' for all the obfuscated class names. This is most useful when you are obfuscating package names and want to combine output from several JCloak'd applications while avoiding name conflict.

SymbolAccessLevel({PUBLIC | PACKAGE | PRIVATE | NONE})

The SymbolAccessLevel setting determines the global access level setting for what fields or methods JCloak will exclude from obfuscation.  JCloak will only obfuscate fields or methods with an access level equal to, or more restrictive than the indicated value, as follows:

.

PUBLIC

All symbols are subject to obfuscation. Symbols that are potentially accessed outside of the obfuscated classes are excluded implicitly. Methods may also be explicitly excluded with an ExcludeMethod() directive.

PACKAGE

Symbols with public or protected access are excluded from obfuscation.   Only package private (default access) and private symbols are obfuscated.

PRIVATE

Only private symbols are obfuscated.

NONE

No symbols are obfuscated.

.

The ExcludeMethod() and/or ClassSettings() or PackageSettings() directives may be used to further limit what symbols are obfuscated

SourceName(string)

Set a source name attribute in all files to the indicated string value. For example, you could put a copyright or other watermark string in your class files using this keyword.

SourceNameFromClass({true | false})

Set to "true" and the source name attribute will be set to the obfuscated or unobfuscated class name. Set to false and the source name will be unmolested. Note that SourceName overrides SourceNameFromClass.

 
Input Directives
AddToClassPath (<path>, <include>, <obfuscate>)

JCloak searches for your application's classes using an internal classpath that is independent of the Java classpath environment. This directive is used to add entries to the target classpath. Multiple AddToClassPath() directives may be specified. The target classpath search order is the same order that the AddToClassPath() directives appear in the configuration file.

You can also cause JCloak to match a jar file from the environment classpath (java.class.path). To specify this use the %CLASSPATH% keyword in the path string. JCloak will match the first occurrence of the string following %CLASSPATH% in the environment classpath. For example:

	AddToClassPath("%CLASSPATH%/rt.jar", false, false) 
This example will match the first occurrence of rt.jar on the Java environment classpath. NOTE this is case sensitive, even on Windows.

At a minimum the target classpath must include the path to your application's main class and the path to the JDK classes.

Three boolean flags (use strings 'true' or 'false' to indicate flag value) are used to control how JCloak handles packages found on the target classpath. These flags are defined in the following table.

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 .  This could be used to include a thirdparty library unmolested in your output jar file.  The GUI makes this the default setting for new classpaths.
True true All classes found on this classpath are loaded and fully obfuscated, unless the remove UN-referenced classes option is set. 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.
 
LoadNameMap(path)

Use this keyword to instruct JCloak to read a name map file containing a map of symbol and class names for incremental obfuscation.  The format and use of name maps is detailed in the operation section Controlling Symbol Renaming

Output Directives

The output class set is the set of classes and resources JCloak saves for your application as the result of the obfuscation process. The tags that follow specify how to save the output set. You can specify multiple output directives and JCloak will generate each in turn.

OutputPath(path)

Use this keyword to indicate that JCloak should write the output set to a directory tree rooted at the directory indicated by the specified path. JCloak will create sub-directories under the root directory as needed for the packages in the output set.

OutputCABFile(path)

Use this keyword to instruct JCloak to generate a CAB file containing the obfuscated class files. The CAB file is compressed using MSZIP format and is compatible with InternetExplorer. The path argument specifies the path and file name of the CAB file.

OutputJARFile(path)

Use this keyword to instruct JCloak to generate a JAR file containing the obfuscated class files. The JAR file is compressed in Zip format and is compatible with Netscape Navigator. The path argument specifies the path and file name of the JAR file.

OutputReferenceNameMap(path)

If this keyword is specified JCloak will write a text file with a sorted list of obfuscated to UN-obfuscated class names followed by a sorted list of obfuscated to unobfuscated symbol names. This map is useful for relating traceback information to the unobfuscated names. The path argument specifies the path and file name of the name map file

OutputZipFile(path)

Use this keyword to instruct JCloak to generate a Zip file containing the obfuscated class files. The Zip file is uncompressed. The path argument specifies the path and file name of the zip file

SaveAbsolutePaths(path)

If this directive is true JCloak will save all paths as absolute paths when it saves the project from GUI mode. If this directive is false any path can be relative. If a path is relative it is relative to the location of the configuration file.

.

SaveNameMap(path)

Use this keyword to instruct JCloak to save a map of symbol and class names for incremental obfuscation.  The format and use of name maps is detailed in the operation section Controlling Symbol Renaming

Other Directives
LoadReferencedClassesOnly({true | false})

Set to "true" and JCloak will only load classes that are referenced from an externally referenced starting class. JCloak assumes classes are referenced externally and uses them as starting points if one or more of the following are true:

  1. The class is named in ClassSettings() or defined in a package named in PackageSettings()
  2. If the class is public access and the global class access level (ClassNameAccessLevel()) is more restrictive than public.
  3. If the class is named as main class (MainClass())

If no class matches this list then JCloak will not load any classes if this directive is set to "true".

If this directive is set to "false" then all classes on any and all included class paths will be loaded.

Note that classes on classpaths that are specified 'include' but not specified 'obfuscate' are always loaded.

HandleRMI({true | false})

Enables (true) or disables (false) the RMI feature. If this feature is enabled when JCloak detects a class that is remote (implements a remote interface) it automatically preserves the classname for the class as well as the _Skel and _Stub classes. In addition JCloak preserves the remoted methods to be compatible with both Java 1 and Java 2 standard RMI

PreserveDynamicallyLoadedClassNames({true | false})

Enables (true) or disables (false) the dynamic class load detection feature.

If enabled JCloak will scan the references starting with the classes that are referenced externally (see LoadReferencedClassesOnly). For each class that is referenced via the starting classes, JCloak checks if the class is explicitly instantiated (via a 'new'). If not is assumed to be dynamically loaded and JCloak preserves it's classname.

If you do not generate the name for a dynamically loaded class, that is you reference the name by using the '.class' operator to get the class object, then JCloak will automatically fix up these names to match the obfuscated classname. Otherwise you must set this directive to 'true' or explicitly preserve the class names using ClassSettings or PackageSettings

Verbose({true | false})

Enables (true) or disables (false) the printing of extended progress information.

Deprecated Directives

.

AddTargetClasspath (directory)

This directive is deprecated,  use AddToClassPath() to specify classpath.

AddWriteablePath (directory)

This directive is deprecated,  use AddToClassPath() to specify classpath.

ClassNameMap(path)

Directive is deprecated, use SaveNameMap()

ExcludeClass(<flags>, <name>)

Directive is deprecated, use ExcludeClassNameObfuscate()

NameMap(path)

Directive is deprecated, use SaveNameMap()

IncludeClass(<name>)

This directive is deprecated.  It is equivilent to ClassSettings(<name>, unspecified, false) or PackageSettings() if <name> is wild carded to indicate entire package is to be included.

The directive includes any class matching <name> in the obfuscation as if it where explicitly referenced by the program classes.  In addition any classes referenced by the included class are also included.


.

Appendix - Method Signature Grammar

Method signatures are in the same format as method descriptors in the class file. The format is:
<method-name><method-descriptor>. The format of the Method Descriptor is as defined in the Java Virtual Machine Specification and outlined below.

A method descriptor represents the parameters that the method takes and the value that it returns:

  MethodDescriptor:

(Type * ) ReturnDescriptor

A return descriptor represents the return value from a method. It is a series of characters generated by the grammar:

  ReturnDescriptor:

Type
V

The character V indicates that the method returns no value (its return type is void).

Type, for parameters and return types is defined as single characters for scalar types, "L<classname>;" for object types. Both maybe prefixed by '[', to indicate an array type, one '[' for each dimension of the array.

The characters for the Type string are as follows:

 B
bytesigned byte 
 C
charcharacter 
 D
doubledouble-precision IEEE 754 float 
 F
floatsingle-precision IEEE 754 float 
 I
intinteger 
 J
longlong integer 
 L<classname>;
object type of class <classname>
 S
shortsigned short 
 Z
boolean
trueor
false[
...			array type, one '[' for each array dimension

.

Note that <classname> is expressed in classfile internal format, that is seperated by '/' in place of '.', for example java.lang.String would be "java/lang/String"

For example, the method descriptor for the method

String toString()

is

toString()LSjava/lang/String;

Note that the method name is not fully qualified.

Or a more complicated example:

byte [] getBytes(int start, int count, String str)

would be

getBytes(IILjava/lang/String;)[B

There are no spaces or commas (,) between the arguement type descriptors.

.