Autojar - create jar archives automatically |
|
By Bernd Eggink, Regionales Rechenzentrum der Universität Hamburg
e-mail: monoped@users.sourceforge.net |
![]() SourceForge project page |
Autojar helps creating jar files of minimal size from different inputs like own classes, external archives etc. It starts from one or more given classes (e.g., an applet), recursively searches the bytecode for references to other classes, extracts these classes from the input archives, and copies them to the output. The resulting archive will only contain the classes you really need. Thus you can keep size and loading time of applets low or make applications independent of installed libraries.
In a similar way, autojar can search directories and archives for other resources (like image files), extract them and copy them to the output.Note that autojar in principle can't know which classes will be loaded dynamically (by Class.forName()). However, starting from version 1.3, one can tell autojar to search the bytecode for invocations of
Class.forName()
and inform you correspondingly. In some cases autojar actually can find out which classes are to be loaded, and add them automatically to the output (see 7.).Autojar uses the excellent bcel package (http://jakarta.apache.org/bcel/).
Note: In the following examples, file- and classpaths are mostly written in linux notation. Windows users will have to replace file paths correspondingly and replace colons by semicolons in classpaths.
Download via the SourceForge project page .
An rpm package is available at http://www.jpackage.org
Version 1.3.1: Minor bug fixes.
With option-v
, autojar now outputs a list of archives that are included in the classpath, but never used.
New option-X
allows exclusion of file and folder names.Version 1.3: Project moved to SourceForge.
Some bugs fixed. Non-class files are now handled correctly even if their names contains more than one dot.
Dynamic loading is detected. Options -d and -a added.
Any command line parameter may be of the form @file, not just the first.Version 1.2.2: Some bugs fixed.
New options: -e, -q, -D.
Wildcards ? and * allowed in search paths.
Improved dependency checking.
Missing files are reported.Version 1.1: Along with option -p, a search path for non-class files may be supplied (e.g., .gif files). Alternatively option -b ("both") tells autojar to search the class path for non-class files as well.
Autojar comes in two flavours with equal functionality. The file autojar.jar is th self-contained version, created by autojar itself. Use it if you don't have BCEL installed. It is started by the commandThe second version, autojar-core.jar, is much smaller, as it contains only the autojar classes. You must have bcel-5.1.jar (or better) in your classpath to use it. Start it like this:autojar [option...] [file...]
(As usual, Windows users have to use semicolon instead of colon in the classpath). Any program parameter (options and files) may be supplied directly on the command line or read from a text file. Example:java -cp autojar-core.jar:bcel.jar de.uni_hamburg.eggink.autojar.Autojar [option...] [file...]
Each line inautojar -o old.jar @params -c in.jar @class-list
params
andclass-list
is considered a program parameter and inserted into the command line sequence.
Option Meaning -b Use classpath for non-class files. -c classpath Class path in the usual format (system dependent), used to search for class files. Default is ".". The name part of each component may contain wildcards * and ?. Example (Linux): Directory
/foo
contains the archivesa.jar
,b.jar
,c.jar
. The expression-c "/ah/oh:/foo/*.jar"
then expands toThe argument must be quoted to prevent expansion of the wildcards by the shell.-c /ah/oh:/foo/a.jar:/foo/b.jar:/foo/c.jar
Example (Windows): Directory
C:\foo
contains the archivesa.jar
,b.jar
,c.jar
. The expression-c C:\ah\oh;C:\foo\*.jar
expands toMultiple instances are merged into one:-c C:\ah\oh;C:\foo\a.jar;C:\foo\b.jar;C:\foo\c.jar
-c /usr/foo -c /usr/bar
is the same as-c /usr/foo:/usr/bar
.-d Autojar searches the bytecode for invocations of Class.forName("name")
and prints corresponding messages (see 7.).-a For each invocation of the kind Class.forName("name")
in the bytecode, autojar tries to find and add the classname
. Implies -d.-D Debug mode, shows more detailed error output (stack trace). Not normally used. -e Search all jars in all Java extension directories (system property "java.ext.dirs"). Without this option, archives in $JAVA_HOME/jre/lib/ext that are to be searched must be specified explicitely. -h Print help and exit. -m manifest Path of the manifest file. The class in the Main-Class entry will be treated like classes given on the command line. -o outfile Output file, mandatory. -p searchpath Search path for non-class files, same format as class path. -q Run silently. Don't issue warnings. -v Verbose output. -x prefix Exclude prefix. Directories and archives in the search path whose path names start with prefix are ignored. Multiple instances are allowed. -- End of options. All remaining parameters are regarded non-options, even if starting with - .
An arbitrary number of file or directory paths may be supplied. What happens depends on the file type:
- Class files (suffix
.class
): If the path names an existing file, this file is added to the archive. Otherwise, if it is a relative name, the class path is searched. If the file can be found, it is added to the archive. Autojar then scans the bytecode, tries to find all classes that this class uses (directly or indirectly), extracts the corresponding files from their archives and adds them, too.- Non-class files: If the path denotes an existing file, it is added to the output archive. If it is a relative path name and a search path for non-class files has been provided (by -p or -b), this path is searched. If the file can be found, it is extracted and added to the output.
- Directories: Directories are added recursively including all their files and subdirectories. All files, including class files, are treated as normal files.
- Jar files: The contents of a jar file are copied to the output, except for the "META-INF" subtree. All classes it contains are then scanned for references to other classes, like described above.
- The special sequence
-C dir file
has the same meaning as in thejar
command: The working directory is changed temporarily todir
, the parameterfile
is evaluated, and then the working directory is changed back again.file
may contain wildcards. A . (dot) means the complete content of the current directory.- The sequence
-X pattern
specifies an exclude pattern. It affects subsequent parameters that generate file lists (directories, wildcard expressions, and "."). Files whose names matchpattern
are skipped. An arbitrary number of such expressions can be inserted into the parameter list; they are internally combined by a logical "or". If the pattern is a hyphen (in the form-X -
or-X-
), the exclude list is cleared, so that "." again denotes all files in in a directory.
This specification provides a convenient way to exclude special directories like.svn
orCVS
, which you normally don't want to include in a jar file.Note that
-C
and-X
are not options. If one of these is the first non-option parameter, it must be prefixed by--
to tell autojar it is not an option.Classes from the Java runtime library will never be included in the output.
At exit, if Option -q is not present, autojar prints a list of missing files.
Since version 1.3, if option -d is supplied, autojar searches the bytecode for invocations ofClass.forName(name)
. A message is printed for each invocation found. Ifname
is a constant (string literal), autojar already knows the class; the message will then readIf option* Dynamic loading: class Test, method g, name="Blah"
-a
is present (implies -d), autojar tries to handle this class like a statically loaded class - that is, find it via the classpath and add it to the output file. It it succeeds, the message will readHowever, if* Dynamic loading: class Test, method g, name="Blah" (RESOLVED)
name
is not a literal, but a normal string reference, autojar can't know the class in advance. Messages about such invocations are printed separately:In this case the output archive may be not self-containded, and using it may result in* Dynamic loading, unknown classname: class Test, method f class Foo, method bar
ClassNotFound
exceptions. Of course this will only happen if the calls toClass.forName()
actually get executed. One has to find that out experimentally.Invocations of
Class.forName()
in compiler generated methods are ignored (see, however, Bugs).
Example 1: An applet consists of a main classMyApplet
plus several other classes, all in the directoryclasses
. Additionally some classes from the archive/local/lib/foo.jar
are used, and all image files in the directoryimages
, which are referred to as"x.gif"
,"y.gif"
etc. (that is, without the directory part). The jar file may then be created like this:If you refer to your image file asautojar -vc classes:/local/lib/foo.jar -o myapplet.jar MyApplet.class -C images '*.gif'
"images/x.gif"
,"images/y.gif"
, replace-C images '*.gif'
by'images/*.gif'
.Example 2: An application consists of a main class
Magic
and 199 additional classes, mixed up with classes from other projects, sources, and all kinds of junk in your working directory (not a particularly good idea, of course). The filemagic.mf
contains the entryMain-Class: Magic
. Now the callautojar -o magic.jar -m magic.mf
creates the archive
magic.jar
, saving you from the need to supply all 200+ names individually.Example 3: An application with main class
com.wow.MyApp
dynamically loads a driver. You have no idea which class that is, but you suspect it might be contained in the archivedrivers.jar
. So you try option -a and include the archive in the classpath:If you are lucky, you get an output likeautojar -av -o myapp.jar -c my.jar:drivers.jar classes/com/wow/MyApp.class
This means that autojar found out the name of the driver and added the class to the archive.* Dynamic loading: class com.wow.MyApp, method init, name="some.nice.Driver" (RESOLVED)
If you are less lucky, the word RESOLVED is missing, which means you now know the name of class, but not where the its file is. This you have to find out yourself. If it'a plain file, symply add it to the command line; if it's in a jar file, add this to autojar's class path.
However, if the first message sounds like
you have bad luck: Autojar couldn't find out the name of the class. The last resort is to start the program anyway and wait for
Dynamic loading, unknown classname: class com.wow.MyApp, method initClassNotFound
exceptions. If they happem, you know which classes are missing. Run autojar again and supply them on the command line this time.Example 4: An Applet creates several graphical buttons. It needs all files from the directory
images
, and the two iconstoolbarButtonGraphics/general/Cut16.gif
andtoolbarButtonGraphics/general/Paste16.gif
from Sun's archive/usr/local/jlfgr-1_0.jar
. The applet loads all images from its own archive:The directory
JButton cutButton = new JButton(new ImageIcon(getClass().getResource("toolbarButtonGraphics/general/Cut16.gif"))), pasteButton = new JButton(new ImageIcon(getClass().getResource("toolbarButtonGraphics/general/Paste16.gif"))), someButton = new JButton(new ImageIcon(getClass().getResource("images/some.png"))), /* ... */images
is controlled by subversion and thus contains a subdirectory.svn
, which should not go into the jar file. So the command could be:If you need all images from the Sun archive or don't care about size, you could also writeautojar -o myapplet.jar -p /usr/local/jlfgr-1_0.jar MyApplet.class \ toolbarButtonGraphics/general/Cut16.gif toolbarButtonGraphics/general/Paste16.gif -X .svn images
This would include the whole content ofautojar -o myapplet.jar /usr/local/jlfgr-1_0.jar MyApplet.class -X .svn images
jlfgr-1_0.jar
in your archive.
If you want to compile autojar yourself, get the bcel package and includebcel.jar
in the classpath. Example:You may then run it like this:javac -d classes -cp classes:bcel.jar -sourcepath . de/uni_hamburg/eggink/autojar/Autojar.java
Optionally you can build a self-contained version by applying autojar to itself:java -cp classes:bcel.jar de.uni_hamburg.eggink.autojar.Autojar parameters...
The filesjava -cp classes:bcel.jar de.uni_hamburg.eggink.autojar.Autojar -vac bcel.jar:classes \ -m autojar.mf -o autojar.jar de.uni_hamburg.eggink.autojar.Autojar.class @classlist
autojar.mf
andclasslist
are included in the directorysrc
of the distribution.classlist
contains a number of class names which BCEL loads dynamically (using string references, so that autojar can't handle them automatically).
Please report bugs via the SourceForge bug tracking system.