使用 jlink 构建自定义运行时镜像的关键是正确声明模块化依赖并基于模块图静态裁剪,仅包含应用实际使用的 JDK 模块及传递依赖;需确保应用为命名模块(含 module-info.java)、显式声明 requires、编译输出至 mods 目录,并通过 --module-path 和 --add-modules 指定模块起点与路径,最终生成精简可执行运行时。

使用 jlink 构建自定义运行时镜像,关键在于模块化(module-info.java)的正确声明与依赖梳理。它不是简单打包,而是基于模块图做静态裁剪 —— 只包含你的应用真正用到的 JDK 模块及其 transitive 依赖。
确保项目已正确模块化
你的应用必须是一个命名模块(named module),即根目录下有 module-info.java,且其中明确声明了 requires 所需的 JDK 模块(如 java.base、java.desktop 等),以及你自己的依赖模块(如果有的话)。
例如:
module hello.world {
requires java.base;
requires java.desktop; // 如果用了 Swing 或 Clipboard 等
}
注意:jlink 不识别自动模块(jar 包无 module-info.class),若第三方库未模块化,需先用 --add-modules 显式引入,并配合 --include-jars 或提前转为可选模块(如用 jmod 封装)。
立即学习“Java免费学习笔记(深入)”;
编译并生成模块路径(--module-path)
jlink 需要一个完整的模块图起点。因此必须先编译你的模块,并将输出(mods/)和所有依赖模块(JDK 自带或自定义 jmod)放在模块路径中。
- 编译模块: javac --module-source-path src -d mods $(find src -name "*.java")
- 确认
mods/hello.world目录存在且含module-info.class和类文件 - JDK 内置模块默认在
$JAVA_HOME/jmods,无需额外准备
执行 jlink 构建最小运行时
命令核心是定位模块起点(--module)并指定输出目录:
jlink \ --module-path mods:$JAVA_HOME/jmods \ --add-modules hello.world \ --output hello-runtime \ --strip-debug \ --compress 2 \ --no-header-files \ --no-man-pages
说明:
-
--add-modules hello.world:告诉jlink从该模块开始解析依赖图(会自动包含其requires的所有 JDK 模块) -
--strip-debug和--compress 2可显著减小体积 -
--no-header-files和--no-man-pages去掉非运行必需内容 - 最终生成的
hello-runtime/bin/java即为专用启动器,只加载所需模块
验证与运行
进入 hello-runtime 目录后,直接运行:
bin/java --module-path mods --module hello.world/hello.Main
也可以把主类打包进模块的 module-info.java 中(用 main-class 属性),再用:
bin/java -m hello.world
此时启动的是完全剥离无关模块的精简 JVM,无 java.xml、java.logging 等默认加载项 —— 除非你在 requires 中显式声明。



















