java --list-modules
:获取所有可用openjdk模块的列表。
jlink --no-header-files --no-man-pages --compress=2 --add-modules <module-list from step 1> --output java-runtime
:创建一个精简的JRE
--module-path
:等效于类路径,告诉JVM在哪里搜索模块。
--add-modules
:这指定要解决的其他根模块。由于所有应用程序代码都在类路径上,因此我们没有初始模块,因此此选项是必需的。我们可以用两种方式指定它,要么使用上述的显式模块列表,要么使用parameter
指示要包含模块路径上的所有内容ALL-MODULE-PATH
。
1、OpendJDK 12创建JRE命令
jlink --no-header-files --no-man-pages --compress=2 --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.management.rmi,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.se,java.security.jgss,java.security.sasl,java.smartcardio,java.sql,java.sql.rowset,java.transaction.xa,java.xml,java.xml.crypto,jdk.accessibility,jdk.aot,jdk.attach,jdk.charsets,jdk.compiler,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,jdk.dynalink,jdk.editpad,jdk.hotspot.agent,jdk.httpserver,jdk.internal.ed,jdk.internal.jvmstat,jdk.internal.le,jdk.internal.opt,jdk.internal.vm.ci,jdk.internal.vm.compiler,jdk.internal.vm.compiler.management,jdk.jartool,jdk.javadoc,jdk.jcmd,jdk.jconsole,jdk.jdeps,jdk.jdi,jdk.jdwp.agent,jdk.jfr,jdk.jlink,jdk.jshell,jdk.jsobject,jdk.jstatd,jdk.localedata,jdk.management,jdk.management.agent,jdk.management.jfr,jdk.naming.dns,jdk.naming.rmi,jdk.net,jdk.pack,jdk.rmic,jdk.scripting.nashorn,jdk.scripting.nashorn.shell,jdk.sctp,jdk.security.auth,jdk.security.jgss,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom,jdk.zipfs --output java-runtime
2、JDK 11按需生成的JRE Runtime
以java -jar FlightRecorder.jar为例,按照能正常运行的需要来生成JRE Runtime,使用JRE Runtime 尽量精简。
1) JDK9之后运行java -jar FlightRecorder.jar报错
Error: Could not find or load main class flightrecorder.Main
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
由于Oracle JDK和OpenJDK二进制文件都不包含JavaFX。幸运的是,Gluon的好人免费提供了OpenJFX项目的构建,因此很容易解决这个问题。
2) 下载JavaFX SDK使用下面命令执行java -jar FlightRecorder.jar
JavaFX SDK下载地址:https://gluonhq.com/products/javafx/
java --module-path /opt/javafx-sdk-11/lib --add-modules=javafx.controls -jar FlightRecorder.jar
3) 使用jdeps命令查看依赖的模块
在应用程序上使用JDK 9版本的jdeps,则会得到以下结果:
> jdeps --list-deps FlightRecorder.jar
java.base
java.logging
java.sql
javafx.base
javafx.controls
javafx.graphics
not found
unnamed module: FlightRecorder.jar
Jdeps在JDK 10中得到了改进,如果我们使用JDK 11版本,则会得到以下信息:
> jdeps --list-deps FlightRecorder.jar
java.base
java.logging
java.sql
尽管显示应用程序使用了哪些模块,但还缺少一些信息。要单独提供JavaFX模块,需要分析它们可能具有的任何JDK模块依赖关系。解决方案是以与Java launcher相同的方式包括模块详细信息:
> jdeps --module-path /opt/javafx-sdk-11/lib --add-modules=javafx.controls --list-deps FlightRecorder.jar
JDK removed internal API/com.sun.media.jfxmediaimpl.platform.ios
java.base
java.datatransfer
java.desktop/java.awt.dnd.peer
java.desktop/sun.awt
java.desktop/sun.awt.dnd
java.desktop/sun.swing
java.logging
java.scripting
java.sql
java.xml
jdk.jsobject
jdk.unsupported
jdk.unsupported.desktop
jdk.xml.dom
4) 生成JRE Runtime
为了使运行时大小尽可能小,我们使用命令行标志来禁止包含头文件和手册页,以及剥离调试信息并在相关时压缩为zip文件格式。要包括的模块列表是jdeps生成的模块。
jlink --no-header-files --no-man-pages --add-modules java.datatransfer,java.desktop,java.logging,java.management,java.naming,java.rmi,java.scripting,java.sql,java.transaction.xa,java.xml,jdk.jsobject,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom --output java-runtime
5) 使用创建好JRE执行命令
java-runtime/bin/java --module-path /opt/javafx-sdk-11/lib --add-modules=javafx.controls -jar FlightRecorder.jar
相关文档:
jlink命令文档:https://docs.oracle.com/javase/9/tools/jlink.htm#JSWOR-GUID-CECAC52B-CFEE-46CB-8166-F17A8E9280E9
Using jlink to Build Java Runtimes for non-Modular Applications
jdeps命令文档:https://docs.oracle.com/javase/9/tools/jdeps.htm#JSWOR690