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. Both the original and the JAXed version of the program are
saved in two zip files <class_name>_big.zip
and
<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:
java jax Hanoi
The output to the screen is:
ProgramName is "Hanoi"
JDK used is Microsoft Corp. version 1.1
jax V5.0-Monday-Mar-1-1999 Copyright IBM 1997-1999. All rights reserved.
Info inside IBM: http://w3.watson.ibm.com/~laffra/jax
Info outside IBM: http://www.alphaWorks.ibm.com/formula/jax
Your free license expires on Jun 1 1999. After this date,
download a new version with major improvements and bug fixes.
Options: obfuscate transform verify devirtualize inline compatibleserialization
loading, this may take a while
finished loading, total 289 classes
starting search for entry points
finished search for entry points
starting RTA analysis
finished RTA analysis
starting inlining
finished inlining
starting class hierarchy transformations
finished class hierarchy transformations
starting name compression
finished name compression
starting devirtualization of method calls
finished devirtualization of method calls
Warning: no "Hanoi_jax.dlc" file with dynamically loaded class names
Warning: no "Hanoi_jax.fcn" file with fixed class names
Warning: no "Hanoi_jax.dim" file with names of dynamically invoked methods
Warning: no "Hanoi_jax.daf" file with names of dynamically accessed fields
starting verification
verifying...
finished verification
saving, this may take a while
saved 22 classes into Hanoi_jax.zip
Analyzed: 31 classes.
Total memory used by jax for processing: 4154928 bytes.
--------------------------------------------------------------
zipfile methods fields classes
--------------------------------------------------------------
before: 58140 285 147 31
after: 22041 184 100 22
--------------------------------------------------------------
savings: 36099 101 47 9
62% 35% 31% 29%
--------------------------------------------------------------
Detailed information saved in: "Hanoi_jax.log"
Compressed project saved in: "Hanoi_jax.zip"
Time used for analysis: 3 seconds.
Thanks for using JAX, a technology preview from IBM.
Please email your feedback to: jax@watson.ibm.com
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.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. 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.
Since Hanoi
does not dynamically load any classes, no such file
exists.
JAX then looks for a Hanoi_jax.fcn
file with classes whose name
must be preserved. Since this is not necessary in the case of Hanoi
,
no such file exists.
After all class files are loaded, JAX 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 *.dcl
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.
Next, the output states the number of class files must be analyzed and saves them to
the file Hanoi_big.zip
that contains uncompressed program packaged
in a zip file. 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, Hanoi_big.zip
,
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:
Hanoi_jax.log
Command line arguments influence the execution of JAX.
Each command line argument will be discussed in turn.
The command
jax Hanoi -noobfuscate
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:
jax Hanoi -notransform
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.