第 3 章 为模块化应用程序创建自定义 Java 运行时环境
您可以使用 jlink
工具从模块化应用程序创建自定义 Java 运行时环境。
先决条件
- 注意
为获得最佳结果,请使用可移植的红帽二进制文件作为 Jlink 运行时的基础,因为这些二进制文件包含捆绑的库。
流程
使用
Logger
类创建一个简单的 Hello World 应用。检查
jdk-17
文件夹中是否存在 OpenJDK 21 二进制文件的基本红帽构建:$ 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)
为应用程序创建一个目录:
$ mkdir -p hello-example/sample
使用以下内容创建
hello-example/sample/HelloWorld.java
文件: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!"); } }
创建名为
hello-example/module-info.java
的文件,并在文件中包含以下代码:module sample { requires java.logging; }
编译应用程序:
$ ./jdk-17/bin/javac -d example $(find hello-example -name \*.java)
在没有自定义 JRE 的情况下运行 您的应用程序:
$ ./jdk-17/bin/java -cp example sample.HelloWorld Mar 09, 2021 10:48:59 AM sample.HelloWorld main INFO: Hello World!
前面的例子显示了需要 311 MB 的 OpenJDK 基础构建来运行单个类。
(可选) 您可以检查红帽构建的 OpenJDK,并为您的应用程序查看许多非必需的模块:
$ 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
这个示例
Hello World
应用有非常少的依赖项。您可以使用 jlink 为应用程序创建自定义运行时镜像。使用这些镜像,您只能使用所需的红帽构建 OpenJDK 依赖项来运行应用程序。
创建应用程序模块:
$ 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
使用所需模块创建自定义 JRE,并为您的应用程序创建自定义应用程序启动程序:
$ ./jdk-17/bin/jlink --launcher hello=sample/sample.HelloWorld --module-path sample-module --add-modules sample --output custom-runtime
列出生成的自定义 JRE 的模块。
请注意,只有一部分原始红帽构建的 OpenJDK 会保留。
$ 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
注意红帽构建的 OpenJDK 将自定义 Java 运行时镜像的大小从 313 M 运行时镜像减小到 50 M 运行时镜像。
使用
hello
launcher 启动应用程序:$ ./custom-runtime/bin/hello Jan 14, 2021 12:13:26 PM HelloWorld main INFO: Hello World!
您的示例应用程序生成的 JRE 没有除
java.base
、java.logging
和sample
模块之外的任何其他依赖项。您可以在
custom-runtime
中发布与自定义运行时捆绑的应用程序。此自定义运行时包括您的应用程序。注意您必须使用基本红帽构建 OpenJDK 的基本安全更新,为应用程序重建自定义 Java 运行时镜像。
更新于 2024-05-10