JAX is an application extraction tool for Java that reduces the program's size. JAX extracts the necessary classes, methods, and fields from a Java application (or applet), applies some optimizations and compression techniques. We measured size reductions ranging from 30% to 80% on real-life Java applications, where the larger size reductions generally occur for large, library-based applications. We have succesfully used JAX on applications of up to 2300 classes.
You should use JAX if you want to reduce the size, or obfuscate your Java program.
JAX is available on alphaWorks. Follow the instructions to download it.
JAX is written in 100% pure Java, and runs on any platform that uses Sun's JDK or other compatible VMs.
Documentation is provided in HTML files in the download package.
JAX takes as input a the name of a Java class that represents the Java program
whose size you want to reduce. Since JAX is written in Java, you run JAX
the same way you would run any other Java program.
java jax [command_line_options] <class_name>
Where:
<class_name>
command_line_options
(optional) are:-version
-help
-notransform
-noinline
-nodevirtualize
-noobfuscate
-noverify
-nocompatibleserialization
JAX generates a zip file and a log file.
<class_name>_jax.zip
is the compressed program <class_name>_jax.log
is the log file JAX looks for 4 optional input files in the current directory:
<class_name>_jax.dlc
contains the names of all classes that are loaded dynamically <class_name>_jax.fcn
contains the names of all classes whose name must be preserved<class_name>_jax.dim
contains the names of all the methods that are called using reflection<class_name>_jax.daf
contains the names of all the fields that are accessed using reflectionUse the "methods" and "fields" programs that are included with the JAX 5.0 distribution to get a listing of available methods and fields in the appropriate format. Example:
java methods java.lang.String
java fields java.lang.String
Please report all bugs by sending mail to jax@watson.ibm.com.
Try JAXing your program with different combinations of the -nocompress,
-noobfuscate, -notransform, or -noobfuscate
command line
options. Each option turns off some extraction, optimization or compression
functionality.
Please tell us if this problem occurs by sending mail to
jax@watson.ibm.com.
JAX requires approximately 40 Kbytes of memory per class processed. To ensure
that the Java VM allocates enough memory while running JAX, tell it to allocate
a larger than usual heap with the -mx option.
For example:
java jax -mx128M <class_name>
JAX is only concerned with the compression of class files and ignores non-class files (e.g., .gif files and .properties files) in the class path. If your application depends on such resource files, please save them in a separate .zip or .jar file. In order to run your compressed application you should include this separate resource archive to your classpath,
In some application, reflection is used to retrieve the name of a class, and to read a resource (i.e., .gif) file with the same name. In such cases, the name of the class must be preserved in order to run the JAXed application correctly. You can achieve this by including the class in the .fcn file (see above).
In its current form, JAX is an application extractor. It assumes that the JAXed application will not be extended (subclassed) and it will remove methods and fields that are not accessed or invoked. Currently the only mechanism to force the preservation of a class, method, or field is to include it in the .dlc, .dim, or .daf file, respectively. We are working on a better mechanism to support libraries.
It can be difficult to find out where reflection is used in your application,
especially if you use third-party libraries for which you don't have access to
the source code.
To address this problem, we have included a tool called reflect
with the
JAX 5.0 distribution. This tool analyzes a ZIP file, instruments calls to the
reflection API (e.g., calls to Class.forName()
,
Class.newInstance()
, Method.invoke()
,
etc.), and produces an instrumented ZIP file. You can then run the instrumented
application by putting the instrumented ZIP file in your classpath. Running the
instrumented application will produce a log file jax-reflect.log
in which the
intercepted calls to the reflection API are recorded. This will tell you which
classes to list in the .dlc or .fcn file, which methods to list in the .dim file,
and which fields to include in the .daf file.
To instrument your application with reflect
:
MyZipFile.zip
java reflect MyZipFile.zip
MyZipFileR.zip
containing the
instrumented application. reflect
will also produce a log
file reflect.log
telling you which calls it instrumented.
Now put MyZipFileR.zip
in your classpath, and run the
instrumented application. This will produce a log file jax-reflect.log
with information about the calls to the reflection API.
Many Java applications use serialization, which is a mechanism for writing out objects to a file, deserialization for reading serialized objects from a file. You can make your class serializable by having it implement the interface java.io.Serializable. As soon you do this, objects of that type can be serialized, and this is done by writing out the non-static and non-transient fields of the class (and its base classes) in a specific order. Serialization poses some interesting issues for an extraction tool like JAX. What if you would write out an object with the original, uncompressed version of your application, and then try to read them back in with the compressed (JAXed) version of your application? If JAX happens to remove unnecessary fields from a previously serialized class, the serialized objects are no longer compatible, and similar problems occur if JAX would merge serializable classes. To avoid such problems, JAX only applies a limited number of transformations to serializable classes. However, if you don't mind breaking the compatibility between JAXed and unJAXed versions of your applications, you can tell JAX to be more aggressive by specifying the -nocompatibleserialization option. Note: your applications may implement java.io.Serializable indirectly. For example, all applets are serializable.