JEP 493: Linking Run-Time Images without JMODs
| Owner | Severin Gehwolf |
| Type | Feature |
| Scope | JDK |
| Status | Closed / Delivered |
| Release | 24 |
| Component | tools / jlink |
| Discussion | core dash libs dash dev at openjdk dot org, jigsaw dash dev at openjdk dot org |
| Effort | M |
| Duration | M |
| Reviewed by | Alan Bateman, Mandy Chung |
| Endorsed by | Alan Bateman |
| Created | 2024/06/07 13:36 |
| Updated | 2025/02/20 09:55 |
| Issue | 8333799 |
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:
-
jlinkcannot be used to create a run-time image that itself contains thejlinktool. Thejlinktool is in thejdk.jlinkmodule, so this fails:$ jlink --add-modules jdk.jlink --output image Error: This JDK does not contain packaged modules and cannot be used \ to create another run-time image that includes the jdk.jlink moduleWe may revisit this restriction in the future if it proves problematic.
-
jlinkfails if any user-editable configuration files are modified.The JDK's
confdirectory contains various files that developers may edit to configure the JDK. Theconf/security/java.securityfile, in particular, configures security providers, cryptographic algorithms, and so forth. In a default build,jlinkcopies the user-editable configuration files for the JDK's modules from the JDK's JMOD files. Without JMOD files,jlinkcopies the configuration files from the run-time image, and fails if any of the files differ from the original files:$ jlink --add-modules java.xml --output image Error: [...]/bin/conf/security/java.security has been modifiedThis restriction prevents
jlinkfrom creating a run-time image with an ad-hoc or insecure configuration. If the security configuration was changed to, e.g., enable an obsolete message-digest algorithm that is disabled by default, then it would be inappropriate to copy that configuration to the new run-time image. -
Cross-linking, e.g., running
jlinkon Linux/x64 to create a run-time image for Windows/x64, is not possible. -
Linking from a run-time image that is itself using
--patch-moduleis not supported. -
Linking by extracting modules from a different run-time image, e.g., by specifying that image to the
--module-pathoption, is not supported.
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.