JEP 493: Linking Run-Time Images without JMODs
Owner | Severin Gehwolf |
Type | Feature |
Scope | JDK |
Status | Completed |
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 | 2024/11/19 17:21 |
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:
-
jlink
cannot be used to create a run-time image that itself contains thejlink
tool. Thejlink
tool is in thejdk.jlink
module, 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 module
We may revisit this restriction in the future if it proves problematic.
-
jlink
fails if any user-editable configuration files are modified.The JDK's
conf
directory contains various files that developers may edit to configure the JDK. Theconf/security/java.security
file, in particular, configures security providers, cryptographic algorithms, and so forth. In a default build,jlink
copies the user-editable configuration files for the JDK's modules from the JDK's JMOD files. Without JMOD files,jlink
copies 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 modified
This restriction prevents
jlink
from 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
jlink
on 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-module
is not supported. -
Linking by extracting modules from a different run-time image, e.g., by specifying that image to the
--module-path
option, 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.