Using jlink to customize Java runtime environment
Abstract
Making open source more inclusive
Red Hat is committed to replacing problematic language in our code, documentation, and web properties. We are beginning with these four terms: master, slave, blacklist, and whitelist. Because of the enormity of this endeavor, these changes will be implemented gradually over several upcoming releases. For more details, see our CTO Chris Wright’s message.
Providing feedback on Red Hat documentation
We appreciate your feedback on our documentation. To provide feedback, you can highlight the text in a document and add comments.
This section explains how to submit feedback.
Prerequisites
- You are logged in to the Red Hat Customer Portal.
- In the Red Hat Customer Portal, view the document in Multi-page HTML format.
Procedure
To provide your feedback, perform the following steps:
Click the Feedback button in the top-right corner of the document to see existing feedback.
NoteThe feedback feature is enabled only in the Multi-page HTML format.
- Highlight the section of the document where you want to provide feedback.
Click the Add Feedback pop-up that appears near the highlighted text.
A text box appears in the feedback section on the right side of the page.
Enter your feedback in the text box and click Submit.
A documentation issue is created.
- To view the issue, click the issue tracker link in the feedback view.
Chapter 1. Overview of jlink
Jlink is a Java command line tool that is used to generate a custom Java runtime environment (JRE). You can use your customized JRE to run Java applications.
Using jlink, you can create a custom runtime environment that only includes the relevant class file.
Chapter 2. Creating a custom Java runtime environment for non-modular applications
You can create a custom Java runtime environment from a non-modular application by using the jlink
tool.
Prerequisites
Install Installing Red Hat build of OpenJDK on RHEL using an archive.
NoteFor best results, use portable Red Hat binaries as a basis for a Jlink runtime, because these binaries contain bundled libraries.
Procedure
Create a simple Hello World application by using the
Logger
class.Check the base Red Hat build of OpenJDK 17 binary exists in the
jdk-17
folder:$ ls jdk-17 bin conf demo include jmods legal lib man NEWS release $ ./jdk-17/bin/java -version openjdk version "17.0.10" 2021-01-19 LTS OpenJDK Runtime Environment 18.9 (build 17.0.10+9-LTS) OpenJDK 64-Bit Server VM 18.9 (build 17.0.10+9-LTS, mixed mode)
Create a directory for your application:
$ mkdir -p hello-example/sample
Create
hello-example/sample/HelloWorld.java
file with the following content:package sample; import java.util.logging.Logger; public class HelloWorld { private static final Logger LOG = Logger.getLogger(HelloWorld.class.getName()); public static void main(String[] args) { LOG.info("Hello World!"); } }
Compile your application:
$ ./jdk-17/bin/javac -d . $(find hello-example -name \*.java)
Run your application without a custom JRE:
$ ./jdk-17/bin/java sample.HelloWorld Mar 09, 2021 10:48:59 AM sample.HelloWorld main INFO: Hello World!
The previous example shows the base Red Hat build of OpenJDK requiring 311 MB to run a single class.
(Optional) You can inspect the Red Hat build of OpenJDK and see many non-required modules for your application:
$ du -sh jdk-17/ 313M jdk-17/
$ ./jdk-17/bin/java --list-modules java.base@17.0.1 java.compiler@17.0.1 java.datatransfer@17.0.1 java.desktop@17.0.1 java.instrument@17.0.1 java.logging@17.0.1 java.management@17.0.1 java.management.rmi@17.0.1 java.naming@17.0.1 java.net.http@17.0.1 java.prefs@17.0.1 java.rmi@17.0.1 java.scripting@17.0.1 java.se@17.0.1 java.security.jgss@17.0.1 java.security.sasl@17.0.1 java.smartcardio@17.0.1 java.sql@17.0.1 java.sql.rowset@17.0.1 java.transaction.xa@17.0.1 java.xml@17.0.1 java.xml.crypto@17.0.1 jdk.accessibility@17.0.1 jdk.attach@17.0.1 jdk.charsets@17.0.1 jdk.compiler@17.0.1 jdk.crypto.cryptoki@17.0.1 jdk.crypto.ec@17.0.1 jdk.dynalink@17.0.1 jdk.editpad@17.0.1 jdk.hotspot.agent@17.0.1 jdk.httpserver@17.0.1 jdk.incubator.foreign@17.0.1 jdk.incubator.vector@17.0.1 jdk.internal.ed@17.0.1 jdk.internal.jvmstat@17.0.1 jdk.internal.le@17.0.1 jdk.internal.opt@17.0.1 jdk.internal.vm.ci@17.0.1 jdk.internal.vm.compiler@17.0.1 jdk.internal.vm.compiler.management@17.0.1 jdk.jartool@17.0.1 jdk.javadoc@17.0.1 jdk.jcmd@17.0.1 jdk.jconsole@17.0.1 jdk.jdeps@17.0.1 jdk.jdi@17.0.1 jdk.jdwp.agent@17.0.1 jdk.jfr@17.0.1 jdk.jlink@17.0.1 jdk.jpackage@17.0.1 jdk.jshell@17.0.1 jdk.jsobject@17.0.1 jdk.jstatd@17.0.1 jdk.localedata@17.0.1 jdk.management@17.0.1 jdk.management.agent@17.0.1 jdk.management.jfr@17.0.1 jdk.naming.dns@17.0.1 jdk.naming.rmi@17.0.1 jdk.net@17.0.1 jdk.nio.mapmode@17.0.1 jdk.random@17.0.1 jdk.sctp@17.0.1 jdk.security.auth@17.0.1 jdk.security.jgss@17.0.1 jdk.unsupported@17.0.1 jdk.unsupported.desktop@17.0.1 jdk.xml.dom@17.0.1 jdk.zipfs@17.0.1
This sample
Hello World
application has very few dependencies. You can use jlink to create custom runtime images for your application. With these images you can run your application with only the required Red Hat build of OpenJDK dependencies.
Determine module dependencies of your application using
jdeps
command:$ ./jdk-17/bin/jdeps -s ./sample/HelloWorld.class HelloWorld.class -> java.base HelloWorld.class -> java.logging
Build a custom java runtime image for your application:
$ ./jdk-17/bin/jlink --add-modules java.base,java.logging --output custom-runtime $ du -sh custom-runtime 50M custom-runtime/ $ ./custom-runtime/bin/java --list-modules java.base@17.0.10 java.logging@17.0.10
NoteRed Hat build of OpenJDK reduces the size of your custom Java runtime image from a 313 M runtime image to a 50 M runtime image.
You can verify the reduced runtime of your application:
$ ./custom-runtime/bin/java sample.HelloWorld Jan 14, 2021 12:13:26 PM HelloWorld main INFO: Hello World!
The generated JRE with your sample application does not have any other dependencies.
You can distribute your application together with your custom runtime for deployment.
NoteYou must rebuild the custom Java runtime images for your application with every security update of your base Red Hat build of OpenJDK.
Chapter 3. Creating a custom Java runtime environment for modular applications
You can create a custom Java runtime environment from a modular application by using the jlink
tool.
Prerequisites
Install Installing Red Hat build of OpenJDK on RHEL using an archive.
NoteFor best results, use portable Red Hat binaries as a basis for a Jlink runtime, because these binaries contain bundled libraries.
Procedure
Create a simple Hello World application by using the
Logger
class.Check the base Red Hat build of OpenJDK 17 binary exists in the
jdk-17
folder:$ ls jdk-17 bin conf demo include jmods legal lib man NEWS release $ ./jdk-17/bin/java -version openjdk version "17.0.10" 2021-01-19 LTS OpenJDK Runtime Environment 18.9 (build 17.0.10+9-LTS) OpenJDK 64-Bit Server VM 18.9 (build 17.0.10+9-LTS, mixed mode)
Create a directory for your application:
$ mkdir -p hello-example/sample
Create
hello-example/sample/HelloWorld.java
file with the following content:package sample; import java.util.logging.Logger; public class HelloWorld { private static final Logger LOG = Logger.getLogger(HelloWorld.class.getName()); public static void main(String[] args) { LOG.info("Hello World!"); } }
Create a file called
hello-example/module-info.java
and include the following code in the file:module sample { requires java.logging; }
Compile your application:
$ ./jdk-17/bin/javac -d example $(find hello-example -name \*.java)
Run your application without a custom JRE:
$ ./jdk-17/bin/java -cp example sample.HelloWorld Mar 09, 2021 10:48:59 AM sample.HelloWorld main INFO: Hello World!
The previous example shows the base Red Hat build of OpenJDK requiring 311 MB to run a single class.
(Optional) You can inspect the Red Hat build of OpenJDK and see many non-required modules for your application:
$ du -sh jdk-17/ 313M jdk-17/
$ ./jdk-17/bin/java --list-modules java.base@17.0.1 java.compiler@17.0.1 java.datatransfer@17.0.1 java.desktop@17.0.1 java.instrument@17.0.1 java.logging@17.0.1 java.management@17.0.1 java.management.rmi@17.0.1 java.naming@17.0.1 java.net.http@17.0.1 java.prefs@17.0.1 java.rmi@17.0.1 java.scripting@17.0.1 java.se@17.0.1 java.security.jgss@17.0.1 java.security.sasl@17.0.1 java.smartcardio@17.0.1 java.sql@17.0.1 java.sql.rowset@17.0.1 java.transaction.xa@17.0.1 java.xml@17.0.1 java.xml.crypto@17.0.1 jdk.accessibility@17.0.1 jdk.attach@17.0.1 jdk.charsets@17.0.1 jdk.compiler@17.0.1 jdk.crypto.cryptoki@17.0.1 jdk.crypto.ec@17.0.1 jdk.dynalink@17.0.1 jdk.editpad@17.0.1 jdk.hotspot.agent@17.0.1 jdk.httpserver@17.0.1 jdk.incubator.foreign@17.0.1 jdk.incubator.vector@17.0.1 jdk.internal.ed@17.0.1 jdk.internal.jvmstat@17.0.1 jdk.internal.le@17.0.1 jdk.internal.opt@17.0.1 jdk.internal.vm.ci@17.0.1 jdk.internal.vm.compiler@17.0.1 jdk.internal.vm.compiler.management@17.0.1 jdk.jartool@17.0.1 jdk.javadoc@17.0.1 jdk.jcmd@17.0.1 jdk.jconsole@17.0.1 jdk.jdeps@17.0.1 jdk.jdi@17.0.1 jdk.jdwp.agent@17.0.1 jdk.jfr@17.0.1 jdk.jlink@17.0.1 jdk.jpackage@17.0.1 jdk.jshell@17.0.1 jdk.jsobject@17.0.1 jdk.jstatd@17.0.1 jdk.localedata@17.0.1 jdk.management@17.0.1 jdk.management.agent@17.0.1 jdk.management.jfr@17.0.1 jdk.naming.dns@17.0.1 jdk.naming.rmi@17.0.1 jdk.net@17.0.1 jdk.nio.mapmode@17.0.1 jdk.random@17.0.1 jdk.sctp@17.0.1 jdk.security.auth@17.0.1 jdk.security.jgss@17.0.1 jdk.unsupported@17.0.1 jdk.unsupported.desktop@17.0.1 jdk.xml.dom@17.0.1 jdk.zipfs@17.0.1
This sample
Hello World
application has very few dependencies. You can use jlink to create custom runtime images for your application. With these images you can run your application with only the required Red Hat build of OpenJDK dependencies.
Create your application module:
$ mkdir sample-module $ ./jdk-17/bin/jmod create --class-path example/ --main-class sample.HelloWorld --module-version 1.0.0 -p example sample-module/hello.jmod
Create a custom JRE with the required modules and a custom application launcher for your application:
$ ./jdk-17/bin/jlink --launcher hello=sample/sample.HelloWorld --module-path sample-module --add-modules sample --output custom-runtime
List the modules of the produced custom JRE.
Observe that only a fraction of the original Red Hat build of OpenJDK remains.
$ du -sh custom-runtime 50M custom-runtime/ $ ./custom-runtime/bin/java --list-modules java.base@17.0.10 java.logging@17.0.10 sample@1.0.0
NoteRed Hat build of OpenJDK reduces the size of your custom Java runtime image from a 313 M runtime image to a 50 M runtime image.
Launch the application using the
hello
launcher:$ ./custom-runtime/bin/hello Jan 14, 2021 12:13:26 PM HelloWorld main INFO: Hello World!
The generated JRE with your sample application does not have any other dependencies besides
java.base
,java.logging
, andsample
module.You can distribute your application that is bundled with the custom runtime in
custom-runtime
. This custom runtime includes your application.NoteYou must rebuild the custom Java runtime images for your application with every security update of your base Red Hat build of OpenJDK.
Revised on 2023-08-15 11:40:58 UTC