Jar tool to transform a plain old JAR file to a modular JAR
Mandy Chung
mandy.chung at oracle.com
Fri Apr 8 12:58:30 PDT 2011
This week I pushed the changeset to support modular JAR Files [1].
Below is a proposal to enhance the jar command-line tool to transform
a plain old JAR file into a modular JAR file by adding module metadata
to ease migration. It's also posted at:
http://cr.openjdk.java.net/~mchung/jigsaw/modular-jar-files.txt
Feedback, comments?
Proposal of jar tool enhancement
=======================
Modular JAR File
A modular JAR file is a JAR file that contains a single module definition
file (META-INF/module-info.class). It can be used as a JAR on the class
path and installed as a module in a module library.
o The META-INF directory
* module-info.class
The module-info.class file describes the module metadata.
Grammar of the source file described in [2].
o Signed JAR file
A modular JAR can be signed in the same way as ordinary JAR.
If a modular JAR file is signed, the META-INF/module-info.class
entry must be signed to be installed in a modular library.
Tool to transform a plain old JAR file into a modular JAR
The jar tool will provide the following new options for
generating a module definition file in a jarfile:
--module={module-name @ version}
Generate META-INF/module-info.class entry in the JAR file.
* jarfile name tends to be unnamed or contains '-' character.
The module name will not be inferred from the jarfile name.
--module-info-java={dir}
Output module-info.java in the specified directory.
The jar tool will also recognize if the inputfiles contains
module-info.class (module-info.java and java files for the module
are compiled in module compilation mode output to the same destination
directory) and add module-info.class to the jarfile in the
META-INF directory.
Transform a jar file to a modular JAR
jar uf jarfile --module=m.foo at 1.0
You can also update the jarfile with an existing module-info.class:
jar uf jarfile -C classes module-info.class
Create a modular jar file
jar c[v0M]f jarfile [-C dir] inputfiles --module=m.foo at 1.0
jar c[v0]mf manifest jarfile [-C dir] inputfiles --module=m.foo at 1.0
If module-info.class exists in the given inputfiles, it will
create a META-INF/module-info.class entry:
jar c[v0M]f jarfile module-info.class inputfiles
The jar tool does not analyze the class dependencies of the jarfile.
It will examine the manifest to infer the modules it requires and
main-class for the modular JAR file as follows:
If the "Main-Class" attribute is present in the manifest,
it will use its value in the main entry point for the module.
If the "Class-Path" attribute is present in the manifest,
it will examine the list of jar files listed in the "Class-Path"
attribute and check if they are modular JAR files and add them
in its module dependency.
If any of the jar files on the "Class-Path" attribute does not
exist or not a modular JAR, it will output an error.
jar tool allows unsigned entries be added to a signed jar file.
If module-info.class is an unsigned entry in a signed jar,
installation will fail. Therefore, transforming an existing signed
jar to a modular jar file requires re-signing. This is consistent
with the existing behavior when the manifest is updated after it
is signed that throws SecurityException at runtime.
To modularize a set of existing jar files (one may depend on
another specified in the "Class-Path" attribute), developers
can run the jar tool on the existing jar files in an order
of walking the dependency graph from the leaf node to the root,
if possible, or have to create the module-info.java and compile
it and add to each jar file. The jar tool can provide an
option to specify the module the jar file requiring:
--require-module={module-name [version-query]}
Specify the module it requires. Multiple --require-module
options can be specified.
Rather than specifying the modules a jar file requires in a
command-line, developers might just prefer to create the
module-info.java and add to the jar.
The proposal is to support the simple case first and check out
existing libraries and applications to determine if the
--require-module option is really helpful in practice in
migrating them to modular jars.
Example Usage
Modularize an existing JAR file
$ jar uf astro.jar --module=org.astro at 2.0
$ jar uf greetings.jar --module=com.greetings at 0.1
- module dependency and main entry point are inferred
from the manifest
Specify a version range in the require-module option:
$ jar uf greetings.jar --module=com.greetings at 0.1 --require-module="org.astro@<=2.0"
Compile and package a modular JAR file
$ javac -d modules -modulepath modules<java files>
$ jar cf astro.jar -C modules/org.astro .
$ jar cfm greetings.jar manifest -C modules/com.greetings .
- module-info.class exists in the modules/com.greetigs
and modules/org.astro directory
Installing a modular JAR file in the module library
$ jmod install greetings.jar astro.jar
Launch the module installed above in module mode
$ java -m com.greetings
Launch a modular JAR file in legacy mode
$ java -jar greetings.jar
References
[1] http://hg.openjdk.java.net/jigsaw/jigsaw/jdk/rev/0d838b758d8b
[2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2011-March/001201.html
More information about the jigsaw-dev
mailing list