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

Implement JEP 493: Linking Run-Time Images without JMODs

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 24
    • tools
    • None
    • behavioral
    • minimal
    • Hide
      Using the run-time image as the base for a link needs to be enabled with a configure option at build time: `--enable-linkable-runtime`. Using the run-time image as base for linking has some minimal risk. 1) Prior this change, when the 'jmods' folder didn't exist the jlink was aborted. After this change, and a build with `--enable-linkable-runtime` is being used as the base, jlink would continue the link using the run-time image based mode applying the anti-delta to packaged modules. 2) Files on the file system could be changed before deriving a custom image from them. Mitigation of the risk of modified files in the file system is provided by including hash sums of those files and failing the runtime-based link when files have been externally modified. Furthermore, a test has been added to compare the output of linking a `java.se` runtime using packaged modules as compared to a `java.se` link using the run-time image. The result is binary identical. Run-time linking an image including the `jdk.jlink` module is prohibited.
      Show
      Using the run-time image as the base for a link needs to be enabled with a configure option at build time: `--enable-linkable-runtime`. Using the run-time image as base for linking has some minimal risk. 1) Prior this change, when the 'jmods' folder didn't exist the jlink was aborted. After this change, and a build with `--enable-linkable-runtime` is being used as the base, jlink would continue the link using the run-time image based mode applying the anti-delta to packaged modules. 2) Files on the file system could be changed before deriving a custom image from them. Mitigation of the risk of modified files in the file system is provided by including hash sums of those files and failing the runtime-based link when files have been externally modified. Furthermore, a test has been added to compare the output of linking a `java.se` runtime using packaged modules as compared to a `java.se` link using the run-time image. The result is binary identical. Run-time linking an image including the `jdk.jlink` module is prohibited.
    • add/remove/modify command line option, Other
    • JDK

      Summary

      Add support for linking a custom runtime without packaged modules being present. Instead, use the current run-time image (a.k.a. lib/modules image) and associated native binaries and auxiliary files from the current installed image.

      Problem

      Linking custom run-time images, specific to particular applications, currently require packaged modules of the JDK to be present (jmods folder in a JDK install with modules within, for example java.base.jmod for the java.base module). Packaged modules, however, duplicate content already present in the JDK runtime image and are only needed for linking custom run-time images. Packaged modules don't influence run-time behaviour. Since packaged modules can add to the total size that a JDK installation takes on disk (~ 80-90MB extra disk space), it's been fairly common to not include them by default and make them available with a separate installable unit (e.g. in Linux RPM installers[1]). When Linux installers choose to do this, linking custom run-time images is not possible without also bringing in the extra installable unit. This problem is exacerbated when the JDK installation has been provided by a third party in a container. Supporting links based on the run-time image would allow for more flexible usage of the jlink tool (e.g. to reduce the set of included modules in a custom JDK run-time image)

      Solution

      The proposed solution is to allow for an additional mode to link a custom run-time image that is based on the current run-time image of the system if a user enables such a mode with the --enable-linkable-runtime configure option. The bytecode for the class files is being taken from the run-time image's jimage (lib/modules) provided those bytecodes don't differ from the ones in packaged modules. If they differ, the original bytecodes from packaged modules are restored at link-time using a delta file packaged in the jimage part of the jdk.jlink module. It's not a goal of this proposal to eliminate the packaged modules jlink workflow as the run-time image based link's primary goal would be to further reduce a larger JDK run-time image into a smaller one. The proposed solution also acknowledges the fact that cross-links for a platform other than the current run-time system would not be possible.

      Alternatives are to add the --keep-packaged-modules hidden jlink option when linking custom run-time images. This option isn't very widely known and isn't turned on by default when linking custom run-time images. More importantly, using --keep-packaged-modules doesn't solve the extra disk space problem.

      Specification

      The run-time image based link is implemented by comparing the optimized jimage of a JDK build, produced by jlink, with the classes and resources of packaged modules. This difference is then being used to create a run-time image of the JDK that can then be used for linking. It does so by serializing those differences into the jimage file on a per module basis. Furthermore, tracking of non-class and -resource files of a module is being done so as to be able to determine the correct module contents. Native resources, configuration and license files are being tracked in a small plain text file in order to support the run-time image based link. Those small text files are part of the jdk.jlink module in package jdk.tools.jlink.internal.runtimelink (e.g. for the java.base module that file is called fs_java.base_files). The differences to the packaged modules view of classes and resources are being recorded in the jdk.jlink module's jdk.tools.jlink.internal.runtimelink package (e.g. for the java.base module that file is called diff_java.base and might be potentially empty). Both files get generated at JDK build time when --enable-linkable-runtime configure option is used. When a JDK installation has been enabled for run-time linking and the absence of packaged modules is being detected, i.e. the jmods folder is missing in $JAVA_HOME, then a run-time image based link is being performed. The jdk.jlink module needs to be present in the base run-time image used for the link. In order to produce a run-time link enabled JDK, the JDK needs to be built with the --enable-linkable-runtime configure option.

      If the current JDK image hasn't been enabled for run-time image based linking at build time an error is shown:

      $ jlink --add-modules java.base --output ./build/java.base-runlink
      Error: This JDK does not support linking from the current run-time image

      On a JDK build that has been run-time image link enabled, jlink --help shows this capability in its output:

      $ jlink --help
      [...]
      Capabilities:
            Linking from run-time image enabled

      Conversely, for a JDK build that doesn't have the run-time image link capability it shows this in jlink --help:

      $ jlink --help
      [...]
      Capabilities:
            Linking from run-time image disabled

      In addition, with the --verbose option, the run-time image based link mentions that modules are being taken from the run-time image as well as that a run-time image based link is being performed:

      $ jlink --add-modules java.compiler --output ./build/java.base-runlink --verbose
      Linking based on the current run-time image
      java.base jrt:/java.base (run-time image)
      java.compiler jrt:/java.compiler (run-time image)
      
      Providers:
        java.base provides java.nio.file.spi.FileSystemProvider used by java.base

      Recursive run-time image based links are being prohibited. That is, the jdk.jlink module cannot be added as a module when performing a run-time image based link:

      $ jlink --add-modules jdk.jlink --output ./build/jdk-including-image
      Error: This JDK does not contain packaged modules and 
             cannot be used to create another image with the jdk.jlink module
      $ echo $?
      1

      When a file part of the run-time image has been modified the link is aborted:

      $ ./bin/jlink --add-modules java.base --output ./build/custom-java-base
      Error: /path/to/jdk/conf/net.properties has been modified
      $ echo $?
      1

      Third-party modules can be added to a custom run-time image, but must be specified with the --module-path option. In that case no JDK provided modules can be on the module path since otherwise a jlink using packaged modules would be performed:

      $ jlink --add-modules leaf1 --module-path=test/jmods --verbose --output ./build/custom-module-runlink
      Linking based on the current run-time image
      java.base jrt:/java.base (run-time image)
      leaf1 file:///path/to/test/jmods/leaf1.jmod
      
      Providers:
        java.base provides java.nio.file.spi.FileSystemProvider used by java.base

      In order to implement the build-time generation of the difference to packaged modules a new hidden option for jlink has been added: --generate-linkable-runtime. It is being used when the run-time image for the JDK image is being generated at JDK build time with the feature turned on at configure time.

      The full implementation can be seen in the proposed pull request: https://github.com/openjdk/jdk/pull/14787

      References

      [1] Size example of a jmods sub-package in Fedora: https://koji.fedoraproject.org/koji/rpminfo?rpmID=38044764

            sgehwolf Severin Gehwolf
            sgehwolf Severin Gehwolf
            Alan Bateman, Andrew Hughes, Mandy Chung (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: