JAX is a Java program packaging tool that reduces the program's size. It works by analyzing a Java program, extracting the essential artifacts out of it, appling some optimizations that reduce space overhead, and then compressing what is left. An estimated 30-50% reduction of the original program size is currently feasible with JAX. In addition, a JAXed Java program is also obfuscated. Obfuscation makes the reconstruction of source code from byte codes difficult.
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 <class_name>
JAX uses the current setting of the CLASSPATH variable to detect the location of the <class_name>.class file (in the same way a Java VM would). When loading class <class_name>, JAX will determine the classes <class_name> depends on and automatically load these classes also.
After loading all class files, the class files are analyzed, the essential artifacts are extracted, optimization is preformed, and the remaining artifacts are compressed. The JAXed version of the program is saved to <class_name>_jax.zip. With the default settings, JAX tries to create a zip file that is as small as possible.
We will use a sample program, Hanoi, to explain the usage of JAX. Hanoi can be found in the demo directory in the JAX distribution. So, to reduce the size of the Hanoi program, run the following command:
ProgramName is "Hanoi" JDK used is Sun Microsystems Inc. version IBM Build n120-19990227 jax V5.2-Friday-Mar-19-1999 Copyright IBM 1997-1999. All rights reserved.
Your free license expires on Jun 19 1999. After this date,
Options: obfuscate nokeeppackagenames transform verify devirtualize inline compatibleserialization loading, this may take a while finished loading, total 465 classes
starting search for entry points
starting RTA analysis
starting inlining
starting class hierarchy transformations
starting name compression
starting devirtualization of method calls
Warning: no "Hanoi_jax.inc" file with include/exclude package prefixes
starting verification
saving, this may take a while saved 22 classes into Hanoi_jax.zip Analyzed: 31 classes. Total memory used by jax for processing: 7049744 bytes. --------------------------------------------------------------
Detailed information saved in: "Hanoi_jax.log"
Time used for analysis: 12 seconds.
Thanks for using JAX, a technology preview from IBM.
|
JAX first outputs the version of JAX that is being used, the IBM internal and external websites where JAX information can be obtained, the name of the program, and the version of the Virtual Machine that is being used, and the expiration date of the license. JAX then prints the options that were used when JAXing Hanoi. Since no command line options were specified, the options shown are the defaults. Look at the Frequently Asked Questions for a brief description of the command line options. Below, we will discuss each option in turn.
Before loading Hanoi, Jax tries to find a Hanoi_jax.inc file that contains the specifications for the classes that are to be included in or excluded from , the classes that are to be JAXed. Below is an example of the contents of such a file :
Hanoi_jax.inc:
include *
exclude ltk.* exclude java.* exclude sun.* exclude sunw.* exclude com.ms.* |
Later lines override the earlier lines; Jax just tries to match a class name with one of the prefixes in the list starting with the last one - if no lines are matched Jax assumes that the class is included.
If this file is not specified by the user, Jax will assume the existance
of the following entries:
include *
exclude java.* exclude sun.* exclude sunw.* exclude com.ms.* |
Then, JAX tries to find a
Hanoi_jax.dlc
file that contains the names of all classes that are loaded dynamically.
Since the analysis performed by JAX is not capable of determining the classes
that are dynamically loaded, the *_jax.dlc
file provides a mechanism for the user to specify these classes.
The names of the dynamically loaded classes are fixed. So, user can also
specify the names of the classes which are to be preserved in this file.
Below is an example of the contents of such a file:
com.acme.ClassOne
com.acme.ClassTwo com.acme.ClassThree |
where each line contains the name of a class that is dynamically loaded or the name of the class that is to be preserved.. Since Hanoi does not dynamically load any classes or does not preserve the names of any classes, no such file exists.
After all the class files are loaded, JAX , in addition to printing
the number of classes that are loaded , it also specifies the number of
application classes, basic types, array types, external classes. Then,
it tries to find a Hanoi_jax.dim
file that contains the methods that are called through Java's reflection
API, and a
Hanoi_jax.daf file that
contains the fields that are accessed through Java's reflection API. Since
Hanoi
does not use reflection, these files do not exist either. However, for
applications that use reflection such files must be created. Below is an
example of the contents of such a *.dim file:
com.acme.ClassFour specialMethod1 (I)V
com.acme.ClassFour specialMethod2 (III)I com.acme.ClassFour |
where each line specifies the method by listing (i) the class in which it is contained, (ii) its name, and (iii) its signature. A similar file can be provided for fields that are accessed using reflection.
The next phases of JAX are displayed as starting and finished messages. These phases consist of: (1) determining entry points, (2) determining reachable methods using RTA analysis, (3) method inlining, (4) class hierarchy transformations, (5) name compression, and (6) devirtualization of method calls.
The table that appears next in the output records the reduction in size of Hanoi after being JAXed. The before row specifies the statistics for the uncompressed program, the after row specifies the statistics for the compressed program, Hanoi_jax.zip, and the savings row specifies the per centage of savings that occur in the compressed program. The first column, labeled zipfile, specifies the size of the zip files, the second column, methods, specifies the number of methods, the third column, fields, specifies the number of fields, and the forth column, classes, specifies the number of classes in the uncompressed and the compressed programs. The entry of 62% in the saving row for the zipfile column is the ESTIMATED overall reduction in program size (the "results" reported by JAX are estimates because it cannot tell which of the classes available on the ClassPath belong to your application). JAX, when it can, removes and merges classes; thus, the 29% reduction in the number of classes. JAX eliminates unreachable methods and unneccessary fields, hence the reduction in the number of methods and fields (reported 35% and 31% for Hanoi, respectively) .
JAX generates a log file:
java jax -noobfuscate Hanoi
will do as much analysis, extraction and optimization on JAX as it can, but will not change names of internal classes, methods, and fields. By default, JAX changes those names to short ones, saving space.
The algorithm to determine which methods and fields are live in Hanoi is a generalization of the RTA algorithm developed at IBM T.J. Watson Research Center and adapted for Java.
JAX performs advanced class hierarchy analysis to determine the relationships between various classes and interfaces, whether certain classes are instantiated or not, and whether classes have overlapping field and methods declarations. This information is used to decide whether or not classes can be removed or merged (by merging a subclass with its parent class and changing all references to the type of the subclass by its parent class). Such class transformations save in declaration space, reduce classloading time, and limit the stress on a Java VM. In some cases, applications rely on the class identity of objects. One example could be where the program logic interrogates an object to obtain its 'class' object, check its identity, and performs actions based on that. JAX analyzes the program to detect such cases (among other things, all calls to "instanceof" are detected). In such cases, the target class will not be merged with others. If for some reason, a program compressed with JAX behaves differently from its original, try JAXing it with:
java jax -notransform Hanoi
That will instruct JAX not to merge any classes at all. The impact of class transformations can be quite big (for Hanoi it is 5%). Please refer to the FAQ for an overview of the other options.