jlink可基于应用真实模块依赖精确组装最小运行时,需JDK 9+且含jmods目录;用jdeps分析依赖后,通过--module-path指向jmods、--add-modules指定模块、--bind-services启用SPI等关键参数构建,并验证输出。

jlink 能直接从 JDK 中裁出只跑你应用所需的最小运行时,不是“打包 JRE”,而是按模块依赖精确组装——前提是你的应用能被 jdeps 分析出真实依赖。
确认 JDK 版本和 jmods 是否可用
OpenJDK 9+ 才有 jlink,且必须带 jmods 目录(不是所有精简版都提供)。运行以下命令验证:
ls $JAVA_HOME/jmods
如果报错或列表为空,说明当前 JDK 构建不包含模块描述文件,jlink 将无法工作。常见于某些 Alpine 镜像、Corretto Lite 或自编译无 --with-jmods 的 OpenJDK。此时需换用完整版 OpenJDK(如 Eclipse Temurin、Red Hat build of OpenJDK)。
分析应用真实模块依赖(尤其非模块化项目)
多数 Java 应用仍是传统 jar 包,没声明 module-info.java。jlink 不能自动猜依赖,必须靠 jdeps 推断:
- 先用
jdeps --print-module-deps your-app.jar快速看基础依赖(但可能漏服务发现、反射加载的模块) - 更稳妥的做法是:运行
jdeps -s -R --multi-release 17 your-app.jar,它会递归扫描所有 class,并标记出用到的 JDK 模块 - 若应用用了 JavaFX、JDBC 驱动、HTTP 客户端等,注意
jdeps可能不报告java.desktop或jdk.unsupported等隐式依赖——得结合启动日志里的NoClassDefFoundError或ClassNotFoundException补全
执行 jlink 构建并验证输出
假设 jdeps 输出含 java.base,java.sql,java.xml,且你用的是标准 OpenJDK:
jlink \ --module-path $JAVA_HOME/jmods \ --add-modules java.base,java.sql,java.xml \ --output myruntime \ --strip-debug \ --no-header-files \ --no-man-pages \ --compress=2
关键点:
-
--module-path必须指向$JAVA_HOME/jmods,不是lib或modules - 加
--bind-services如果应用用到了 SPI(如 JDBC Driver、SLF4J 绑定),否则ServiceLoader找不到实现类 -
--compress=2能再压 10–15% 体积,但首次启动略慢;=0则解压快,适合 Serverless 冷启动敏感场景 - 生成后立刻验证:
myruntime/bin/java -version和myruntime/bin/java -m your.app.Main(确保主类在模块路径或 jar 中正确声明)
JavaFX 或其他第三方模块集成要额外处理
JavaFX 自 JDK 11 起已剥离,不能只靠 $JAVA_HOME/jmods。若你用 OpenJFX SDK:
- 下载对应 JDK 版本的 OpenJFX SDK(如 JDK 21 对应 JavaFX 21),解压后拿到
lib/目录路径 -
jlink命令中--module-path要拼接两个路径:$JAVA_HOME/jmods:/path/to/openjfx/lib -
--add-modules必须显式列出用到的 FX 模块(如javafx.controls,javafx.fxml),不能写ALL-SYSTEM或通配符 - 若要用
jshell,记得加上jdk.jshell,否则生成的运行时里没有这个命令
真正容易被忽略的是服务绑定和资源加载路径——--bind-services 不只是可选项,而是让 Platform.startup()、CSS 解析器、字体渲染器等内部机制正常工作的必要开关。没加它,JavaFX 应用可能黑屏或抛 ServiceConfigurationError。











