JEP 493: Linking Run-Time Images without JMODs

OwnerSeverin Gehwolf
TypeFeature
ScopeJDK
StatusCompleted
Release24
Componenttools / jlink
Discussioncore dash libs dash dev at openjdk dot org, jigsaw dash dev at openjdk dot org
EffortM
DurationM
Reviewed byAlan Bateman, Mandy Chung
Endorsed byAlan Bateman
Created2024/06/07 13:36
Updated2024/11/19 17:21
Issue8333799

Summary

Reduce the size of the JDK by approximately 25% by enabling the jlink tool to create custom run-time images without using the JDK's JMOD files. This feature must be enabled when the JDK is built; it will not be enabled by default, and some JDK vendors may choose not to enable it.

Goals

Allow users to link a run-time image from modules regardless of whether those modules are standalone JMOD files, modular JAR files, or are part of a run-time image linked previously.

Motivation

The installed size of the JDK on the filesystem is important in cloud environments, where container images that include an installed JDK are automatically and frequently copied over the network from container registries. Reducing the size of the JDK would improve the efficiency of these operations.

A complete, installed JDK has two main components: A run-time image, which is the executable Java run-time system, and a set of packaged modules, in the JMOD format, for each module in the run-time image.

The JMOD files are used by the jlink tool when creating custom run-time images. The run-time image in a complete JDK is itself such an image, created from these JMOD files via jlink. Thus every class file, native library, configuration file, and other resource in the run-time image is also present in one of these JMOD files — arguably a massive waste of space.

In fact, the JMOD files in a complete JDK account for about 25% of the JDK's total size. If we could enhance the jlink tool to extract class files, native libraries, configuration files, and other resources from the run-time image itself then we could dramatically reduce the size of the installed JDK by omitting the JMOD files.

Description

The new JDK build-time configuration option --enable-linkable-runtime builds a JDK whose jlink tool can create run-time images without using the JDK's JMOD files. The resulting JDK does not include those files, i.e., there is no jmods directory. It is thus approximately 25% smaller than a JDK built with the default configuration, though it contains exactly the same modules.

$ configure [ ... other options ... ] --enable-linkable-runtime
$ make images

The jlink tool in any JDK build can consume both JMOD files and modular JAR files. In addition, in JDK builds with this feature enabled, jlink can consume modules from the run-time image of which it is part. The --help output of jlink shows whether it has this capability:

$ jlink --help
Usage: jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...]
...
Capabilities:
      Linking from run-time image enabled
$

This means that the jlink tool in use can link JDK modules from the containing run-time image. If it did not have this capability then it would say Linking from run-time image disabled instead.

A version of jlink with the new capability always prefers to consume JDK modules from JMOD files on the module path, if available. It will consume modules from the run-time image of which it is part only if the module java.base is not found on the module path. Any other modules must still be specified to jlink via the --module-path option.

The user experience of running jlink with the new capability is exactly the same as that of running jlink without the capability. If we want to reduce the size of the run-time image by omitting some modules, we can continue to do so by including only the modules we require, yet JMOD files are not needed. For example, to create a run-time image that contains only the java.xml and java.base modules, the jlink invocation is the same:

$ jlink --add-modules java.xml --output image
$ image/bin/java --list-modules
java.base@24
java.xml@24
$

The output of jlink is exactly the same as if the modules were linked from JMOD files. The resulting run-time image is about 60% smaller than a full JDK run-time image.

Invocations for more complex cases are also the same. For example, suppose we want to create a run-time image containing an application module app which requires a library lib. These modules are packaged as modular JAR files in an mlib directory. We specify them to jlink via the --module-path option, as usual:

$ ls mlib
app.jar	lib.jar
$ jlink --module-path mlib --add-modules app --output app
$ app/bin/java --list-modules
app
lib
java.base@24
$

The jlink tool copies the class files and resources for the app and lib modules from the modular JAR files app.jar and lib.jar. It extracts the class files, native libraries, configuration files, and other resources for the JDK's modules from the JDK's run-time image.

The --verbose option of jlink now shows the origin of each module:

$ ls custom-jmods
foo.jmod
$ jlink --add-modules foo \
        --module-path=custom-jmods \
        --verbose \
        --output foo-image
Linking based on the current run-time image
java.base jrt:/java.base (run-time image)
foo file:///path/to/custom-jmods/foo.jmod

Providers:
  java.base provides java.nio.file.spi.FileSystemProvider used by java.base
$

Here the module java.base is extracted from the current run-time image, while the module foo is linked from the JMOD file foo.jmod.

Not enabled by default

The default build configuration will remain as it is today: The resulting JDK will contain JMOD files and its jlink tool will not be able to operate without them. Whether the JDK build that you get from your preferred vendor contains this feature is up to that vendor.

We may propose to enable this feature by default in a future release.

Restrictions

The jlink tool in a JDK built with --enable-linkable-runtime has a few limitations compared to that in a JDK built with the default configuration:

Alternatives

A JDK vendor could provide a JDK's JMOD files as a separate download. Some Linux distributions already do essentially this, by providing one installation package for the JDK run-time image and another for the corresponding JMOD files.

This approach is brittle, since if the second package is not installed then the jlink tool will not work. This approach is, furthermore, not well-suited to cloud environments in which a JDK run-time image and its JMOD files might wind up in different and conflicting container-image layers.