Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8080531

JEP 275: Modular Java Application Packaging



    • Danno Ferrin
    • Feature
    • Open
    • JDK
    • openjfx dash dev at openjdk dot java dot net
    • M
    • M
    • JEP now targeted and on schedule
    • 275



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


      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 will develop a tool defined in JEP 282 jlink: The Java Linker 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.


      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, 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 --<name>=<value> or --<name> <value>.

      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 <fx:application>, <fx:secondaryLauncher> and the new <fx:runtime> task.

      For example:

      <fx:deploy outdir="${bundles.dir}"
          <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:application id="MinesweeperFX"
                          module="fx.minesweeper" <-- new
          <fx:secondaryLauncher name="Test2"
                                module="hello.world" <-- new

      <fx:runtime>, <fx:limit-modules>, <fx:add-modules>, <fx:modular-path> are optional arguments. The module="module name" argument on <fx:application> is used if bundling with a modular application, otherwise if the application is a non-modular application it is invalid. The arguments <fx:limit-modules>, <fx:add-modules>, <fx:modular-path> 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).

      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.


      The packager will be split into two modules:


      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.


      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.


      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.



        Issue Links

          [packager] bootmodules.jimage was renamed to modules Sub-task Resolved Chris Bensen (Inactive)  
          Mac .app bundling Sub-task Resolved Dmitry Cherepanov  
          Mac DMG Installer Sub-task Resolved Chris Bensen (Inactive)  
          Mac PKG Installer Sub-task Resolved Chris Bensen (Inactive)  
          Mac App Store Bunder Sub-task Resolved Chris Bensen (Inactive)  
          Packager to support -m (module name) Sub-task Resolved Chris Bensen (Inactive) 2016-06-09
          JNLP Bundling Support for Application Bundler Sub-task Resolved Chris Bensen (Inactive)  
          Linux Application Image Bundling Sub-task Resolved Dmitry Cherepanov  
          Linux DEB Installer Sub-task Resolved Dmitry Cherepanov  
          Linux RPM Installer Sub-task Resolved Dmitry Cherepanov  
          Windows App Image Sub-task Resolved Dmitry Cherepanov  
          Windows EXE Installer Sub-task Resolved Dmitry Cherepanov  
          Windows MSI Installer Sub-task Resolved Dmitry Cherepanov  
          App Bundler: Dependent Modules Sub-task Resolved Danno Ferrin (Inactive)  
          App Bundler: Dependent modules in jimage Sub-task Resolved Danno Ferrin (Inactive)  
          App Bundler: Limit Modules Sub-task Resolved Danno Ferrin (Inactive)  
          Build Changes Sub-task Resolved Chris Bensen (Inactive)  
          Multiple Launchers Support Modules Sub-task Resolved Chris Bensen (Inactive)  
          [packager] Linux javapackager doesn't work Sub-task Resolved Chris Bensen (Inactive)  
          [packager] Module Path Packager Arguments Sub-task Resolved Chris Bensen (Inactive)  
          Add helper class in jdk.jlink for packager use to avoid coordination with FX and JDK builds Sub-task Closed Chris Bensen (Inactive) 2016-04-21
          App Bundler: Automatic Module Dependency Calculation Sub-task Resolved Chris Bensen (Inactive) 2016-05-20
          App Bundler: Detect Dependent Module from module path or classpath Sub-task Resolved Chris Bensen (Inactive) 2016-06-09
          Adjust to jlink API Changes Sub-task Resolved Chris Bensen (Inactive)  
          [packager] Change Java Packager CLI arguments Sub-task Resolved Chris Bensen (Inactive)  
          [packager] Refactor Public API Sub-task Resolved Chris Bensen (Inactive) 2016-06-24
          Revisit javapackager module path related options Sub-task Resolved Chris Bensen (Inactive) 2016-06-09
          Ant Support for modular arguments Sub-task Resolved Chris Bensen (Inactive) 2016-06-24



              cbensen Chris Bensen (Inactive)
              shemnon Danno Ferrin (Inactive)
              Chris Bensen Chris Bensen (Inactive)
              Alan Bateman, Kevin Rushforth, Mandy Chung
              Kevin Rushforth
              1 Vote for this issue
              13 Start watching this issue