Autojar - create jar archives automatically |
|
| By Bernd Eggink, Regionales Rechenzentrum der Universität Hamburg
e-mail: monoped@users.sourceforge.net |
German version
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-Xallows 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-listparamsandclass-listis 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
/foocontains 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.jarExample (Windows): Directory
C:\foocontains the archivesa.jar,b.jar,c.jar. The expression-c C:\ah\oh;C:\foo\*.jarexpands 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/baris 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 filehas the same meaning as in thejarcommand: The working directory is changed temporarily todir, the parameterfileis evaluated, and then the working directory is changed back again.filemay contain wildcards. A . (dot) means the complete content of the current directory.- The sequence
-X patternspecifies an exclude pattern. It affects subsequent parameters that generate file lists (directories, wildcard expressions, and "."). Files whose names matchpatternare 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.svnorCVS, which you normally don't want to include in a jar file.Note that
-Cand-Xare 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. Ifnameis a constant (string literal), autojar already knows the class; the message will then readIf option* Dynamic loading: class Test, method g, name="Blah"-ais 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)nameis 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 barClassNotFoundexceptions. 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 classMyAppletplus several other classes, all in the directoryclasses. Additionally some classes from the archive/local/lib/foo.jarare 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
Magicand 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.mfcontains the entryMain-Class: Magic. Now the callautojar -o magic.jar -m magic.mfcreates the archive
magic.jar, saving you from the need to supply all 200+ names individually.Example 3: An application with main class
com.wow.MyAppdynamically 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.classThis 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 forDynamic loading, unknown classname: class com.wow.MyApp, method initClassNotFoundexceptions. 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.gifandtoolbarButtonGraphics/general/Paste16.giffrom Sun's archive/usr/local/jlfgr-1_0.jar. The applet loads all images from its own archive:The directoryJButton 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"))), /* ... */imagesis 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 imagesThis would include the whole content ofautojar -o myapplet.jar /usr/local/jlfgr-1_0.jar MyApplet.class -X .svn imagesjlfgr-1_0.jarin your archive.
If you want to compile autojar yourself, get the bcel package and includebcel.jarin the classpath. Example:You may then run it like this:javac -d classes -cp classes:bcel.jar -sourcepath . de/uni_hamburg/eggink/autojar/Autojar.javaOptionally 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 @classlistautojar.mfandclasslistare included in the directorysrcof the distribution.classlistcontains 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.