JDK-8080531 : JEP 275: Modular Java Application Packaging
  • Type: JEP
  • Component: deploy
  • Sub-Component: packager
  • Priority: P3
  • Status: Closed
  • Resolution: Delivered
  • Fix Versions: 9
  • Submitted: 2015-05-15
  • Updated: 2017-04-27
  • Resolved: 2017-04-27
Related Reports
Relates :  
Relates :  
Relates :  
Sub Tasks
JDK-8139997 :  
JDK-8140000 :  
JDK-8140002 :  
JDK-8140003 :  
JDK-8140004 :  
JDK-8140020 :  
JDK-8140021 :  
JDK-8140022 :  
JDK-8140024 :  
JDK-8140025 :  
JDK-8140026 :  
JDK-8140027 :  
JDK-8140028 :  
JDK-8140030 :  
JDK-8140037 :  
JDK-8140038 :  
JDK-8146582 :  
JDK-8148307 :  
JDK-8148978 :  
JDK-8150990 :  
JDK-8150991 :  
JDK-8151417 :  
JDK-8151568 :  
JDK-8151569 :  
JDK-8154102 :  
JDK-8154480 :  
JDK-8154481 :  
JDK-8154895 :  
Description
Summary
-------

Integrate features from [Project Jigsaw][jig] into the Java Packager, including module awareness and custom run-time creation.

[jig]: http://openjdk.java.net/projects/jigsaw


Motivation
----------

The Java Packager (`javapackager`) has always generated huge binaries when it is asked to bundle a run-time as part of its packaging due to the size of the JRE. [Project Jigsaw][jig] will develop a tool defined in [JEP 282 jlink: The Java Linker][jep282] that allows creation of run-time images that contain a subset of the standard and JDK modules enabling the Java Packager to reduce the size of the bundled runtime image.

Description
-----------

For the most part, the Java Packager workflow will stay the same.  New tools from Jigsaw will be added, and in some cases replace some steps.


### Only Generate Java 9 Applications

The Java Packager will only create applications that use the JDK 9 run-time. This will simplify a lot of code paths and assumptions with regard to tools used to assemble applications and java run-times. If a user wants to create a Java 8 application then the Java 8 version of Java Packager shipped with JDK 8 will continue to work. We assume that
the number of self-contained applications that need to work simultaneously on Java 8 and Java 9 will be essentially zero, since the application brings its own JVM with it.


### Use `jlink` to generate embedded Java Run-time and Application Images

Currently JREs are copied and unneeded portions are deleted from the copied run-time. 

The [Java linker tool](http://openjdk.java.net/jeps/282), `jlink`, provides a means to generate a JRE image that contains only the required modules. Furthermore `jlink` may expose some hooks for its image-generation process that we may take advantage of to further customize the image by, for example, adding the removal of executables to the `jlink` processing, or compression.

The Java Packager will call `jlink` to create an application run-time image that will be embedded in the application image. The Java Packager will fail with an appropriate error if `jlink` fails. It is expected that the packaged modules will ship with JDK 9.

The `jlink` tool includes a plugin and extension mechanism. When using `jlink` to generate the application image we will integrate with those mechanisms so that the output of the `jlink` process is the application image in a proper platform-specific layout. This will have the desirable side effect of making application image generation not dependent on the Java Packager process.


### `javapackager` CLI Arguments, Ant Tasks and Java Packager API

The Java Packager has new CLI arguments to match the rest of the Java toolchain specified in JEP 261 for option syntax and values:

    --add-modules <module>(,<module>)*
    --limit-modules <module>(,<module>)*
    --module-path <path>(:<path>)*
    -p <path>(:<path>)*
    --module <module>/<classname>
    -m <module>/<classname>

To specify an argument for a long option, you can use --&lt;name&gt;=&lt;value&gt; or --&lt;name&gt; &lt;value&gt;.

NOTE: `--module-path` maps to jlink's `--module-path` but with an optional default value. More information below.

There will be new ANT tasks off the &lt;fx:application&gt;, &lt;fx:secondaryLauncher&gt; and the new &lt;fx:runtime&gt; task.

For example:

    <fx:deploy outdir="${bundles.dir}"
               outfile="MinesweeperFX"
               nativeBundles="all"
               verbose="true">

        <fx:runtime strip-native-commands="false"> <-- new
            <fx:add-modules value="java.base"/>
            <fx:add-modules value="jdk.packager.services,javafx.controls"/>
            <fx:limit-modules value="java.sql"/>
            <fx:limit-modules value="jdk.packager.services,javafx.controls"/>
            <fx:module-path value="${java.home}/../images/jmods"/>
            <fx:module-path value="${build.dir}/modules"/>
        </fx:runtime>

        <fx:application id="MinesweeperFX"
                        name="MinesweeperFX"
                        module="fx.minesweeper" <-- new
                        mainClass="minesweeper.Minesweeper"
                        version="1.0">
        </fx:application>

        <fx:secondaryLauncher name="Test2"
                              module="hello.world" <-- new
                              mainClass="com.greetings.HelloWorld">
        </fx:secondaryLauncher>
    </fx:deploy>

&lt;fx:runtime&gt;, &lt;fx:limit-modules&gt;, &lt;fx:add-modules&gt;, &lt;fx:modular-path&gt; are optional arguments. The module="module name" argument on &lt;fx:application&gt; is used if bundling with a modular application, otherwise if the application is a non-modular application it is invalid. The arguments &lt;fx:limit-modules&gt;, &lt;fx:add-modules&gt;, &lt;fx:modular-path&gt; are interchangeable with --add-mods, --limit-mods and --module-path used in this document. See the section Module Configurations for additional module are argument information.

The Java Packager API will get new methods for modular options.

### Strip Native Commands

Stripping the commands such as java.exe has been the default for the Java Packager but some developers need the command line tools such as java.exe. So there will be an option to include the native commands by turning off the removal of stripping of commands:

    --strip-native-commands false


### Add support for modules and module paths

Jigsaw introduces the notion of a "module path" in addition to a classpath. The module path consists of paths to the libraries, JDK modules and the application module. The paths that contain these modules are specified with the command line argument:

    --module-path <path>(:<path>)*

It can be supplied only once and it is a platform path. The root modules and their transitive dependences are linked to create a modular run-time image ([JEP 220][JEP220]).

The developer can supply a path with packaged modules to bundle with a different version of the Java Runtime than the default. If no JDK packaged modules are provided by the developer then the Java Packager will default to using the packaged modules supplied with the version of the JDK that the Java Packager ships with ($JAVA_HOME/jmods).

The Java Packager does not currently provide a mechanism to copy packaged modules to the application run-time image instead of linking into the `jimage`. The most likely need for this scenario would be if the application supports plugins and these modules live outside of the bundled image. If that is the case, the developer will need to override the --module-path and --add-modules using the user JVM argument overrides.


### Module Configurations

There are two types of Java applications that will be bundled using the Java Packager: Non-modular JARs and Modular Applications.

Non-modular JARs consist of a JAR without a module-info.class in the JAR file. Use `-appClass` and `-BmainJar=`. for applications. Developers will use the Java Packager with the same arguments as with previous versions prior to JDK 9 using the `-srcfiles`, `-Bclasspath=`, `-appClass` and `-BmainJar=` arguments. For backwards compatibility no new modular arguments are required and by default the embedded Java Runtime will consist of all redistributable modules, so there will be no size reduction of the bundled runtime. Developers can use `--module-path`, `--add-modules` and `--limit-modules` to include 3rd party modules.

For example:

    javapackager -deploy -v -outdir output -name HelloWorld -Bclasspath=hello.world.jar -native -BsignBundle=false -BappVersion=1.0 -Bmac.dmg.simple=true -srcfiles hello.world.jar -appClass HelloWorld -BmainJar=hello.world.jar

Modular Applications consist of a JAR, exploded module, or packaged module containing a module-info.class. To bundle with a Modular Application the `--module` and `--module-path` arguments must be specified. `--module` is mutually exclusive to `-appClass` and `-BmainJar=`.  `--module-path` must provide a path containing the main module (the module referenced with `--module`). Other modules can be added to the `run-time image` using `--add-modules` and `--limit-modules`. Modules dynamically loaded through core reflection or services must be manually specified with `--add-modules`. The main module and the modules provided by --add-modules will define the root modules. `jlink` will create a run-time image with the specified root modules and their transitive dependencies.

For example:

    javapackager -deploy -v -outdir output -name Test -native -BsignBundle=false -BappVersion=1.0 -Bmac.dmg.simple=true --module-path /path/to/jmod --module hello.world/com.greetings.HelloWorld

This command will produce a run-time image consisting of the main module and all of its transitive dependencies. Other modules can be added via --add-modules option.

### Modules

The packager will be split into two modules:

    jdk.packager
    jdk.packager.services

jdk.packager contains the Java Packager that builds the app bundle and the installers. jdk.packager.services is a module that is bundled with the app bundle that provides access to packager services at runtime such as JVM user arguments.

### JNLP

The bundles that are generated will depend on the input and the options provided. Historically -deploy would generate all native bundles and .jnlp files. Now, -deploy in conjunction with -module will not generate .jnlp files since JNLP does not support the new modular options. -native with no options will generate all native bundles available.

Testing
-------

First and foremost, existing API, command line, and Ant invocations of the Java Packager that worked in JDK 8 should work in JDK 9, so existing tests for the JDK 8 packager should be run.

New tests will need to be written to exercise the new flags exposed to to support `run-time image` generation, module-path specifications, and `jeeps` process interactions.


Risks and Assumptions
---------------------

We assume that the project will be delivered substantially as it has been described.  If large functional parts are moved to later releases, such as the module path and module system, then the corresponding portions of
this JEP will slip as well.


Dependences
-----------

  - [200: The Modular JDK][jep200]
  - [201: Modular Source Code][jep201]
  - [220: Modular Run-Time Images][jep220]
  - [261: Module System][jep261]
  - [282: jlink: The Java Linker][jep282]

[sotms]: http://openjdk.java.net/projects/jigsaw/spec/sotms/
[jig]: http://openjdk.java.net/projects/jigsaw/
[jep200]: http://openjdk.java.net/jeps/200
[jep201]: http://openjdk.java.net/jeps/201
[jep220]: http://openjdk.java.net/jeps/220
[jep261]: http://openjdk.java.net/jeps/261
[jep282]: http://openjdk.java.net/jeps/282
Comments
Chris, modulepath is -mp or -p ? Under section "javapackager CLI Arguments, Ant Tasks and Java Packager API" currently it is written as -p <path>(:<path>)*
27-06-2016

The default for -stripexecutables is true, so either missing or containing "-stripexecutables true" the executables are stripped. This is backwards compatible. By adding "-stripexecutables false" the executables such as java.exe should remain. I think there may be a small bug in there with the logic that I will have to look at. If you have a bug please file it. My intent was to allow "-stripexecutables=false" but the argument parsing doesn't support that and there isn't time to rewrite it and for it to be backwards compatible.
23-03-2016

Working of stripexecutables is in reverse order as mentioned above: What i noticed in product is : 1. without "-stripexecutables" argument in command line ----> executables are not removed. 2. with "stripexecutables" argument in command line -----> executables are removed. is this what required or other way round ?
23-03-2016

Now that it has gone candidate, how hard is it to tweak text? I'de like to strike the section on optional use of jmods, and require the modules to be present as jmods or in exploded forms. Strike > The new `jlink` process will be used to create the bundled JRE if the JDK > 9 JMOD files are available to the packager. In the event the JMODs are > not available, then the old behavior of using an existing image and > stripping the image will be used. and replace with > The new process will require a JDK with JMOD files or exploed modules > usable by `jlink.` Building self contained applicaitons without `jlink` will > not be supported. I missed that that section was there when I re-worked the support of older version and removed those code paths.
24-09-2015