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

JEP 275: Modular Java Application Packaging

    Details

    • Author:
      Danno Ferrin
    • JEP Type:
      Feature
    • Exposure:
      Open
    • Subcomponent:
    • Scope:
      JDK
    • Discussion:
      openjfx dash dev at openjdk dot java dot net
    • Effort:
      M
    • Duration:
      M
    • Alert Status:
       Green
    • Alert Reason:
      JEP now targeted and on schedule
    • JEP Number:
      275

      Description

      Summary

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

      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 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.

      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, 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}"
                 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>

      <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.

      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

        Issue Links

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

          Activity

          Hide
          shemnon Danno Ferrin (Inactive) added a comment -
          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.
          Show
          shemnon Danno Ferrin (Inactive) added a comment - 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.
          Hide
          rgangadhar Ramesh Gangadhar added a comment -
          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 ?
          Show
          rgangadhar Ramesh Gangadhar added a comment - 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 ?
          Hide
          cbensen Chris Bensen added a comment - - edited
          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.
          Show
          cbensen Chris Bensen added a comment - - edited 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.
          Hide
          rgangadhar Ramesh Gangadhar added a comment -
          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>)*
          Show
          rgangadhar Ramesh Gangadhar added a comment - 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>)*

            People

            • Assignee:
              cbensen Chris Bensen
              Reporter:
              shemnon Danno Ferrin (Inactive)
              Owner:
              Chris Bensen
              Reviewed By:
              Alan Bateman, Kevin Rushforth, Mandy Chung
              Endorsed By:
              Kevin Rushforth
            • Votes:
              1 Vote for this issue
              Watchers:
              11 Start watching this issue

              Dates

              • Due:
                Created:
                Updated:
                Resolved:
                Integration Due: