jlink定制精简jre的核心是依赖分析而非手动删减:先用jdeps精准识别应用所需模块(如java.base、java.logging),再通过jlink --module-path $java_home/jmods --add-modules 指定模块自动生成最小闭包运行时,配合--strip-debug、--compress=2等参数优化体积与启动性能。

用 jlink 定制精简版 JRE,核心是只保留应用真正需要的模块,不带多余类库和本地库,从而降低内存占用、加快启动、减小体积。关键不在“删文件”,而在“算依赖”——让 jlink 自动识别并打包最小闭包。
先搞清你的程序到底依赖哪些模块
盲目指定 --add-modules 容易漏依赖或带进冗余模块。推荐用 jdeps 分析:
- 运行
jdeps --module-path lib/ --class-path your-app.jar your.main.Class,查看直接/间接依赖的模块名(如 java.base、java.logging、java.naming) - 加
--jdk-internals可检查是否意外用了内部 API(这类依赖可能导致运行时报错) - 如果项目已模块化(有 module-info.class),jdeps 会更准确;未模块化的 jar,建议先用
--multi-release 17(按目标 JDK 版本适配)
用 jlink 构建最小运行时镜像
jlink 不处理你的代码,只生成运行时环境。它从 JDK 的 jmods/ 目录读取模块定义,输出一个可执行目录:
- 基础命令示例:
jlink --module-path $JAVA_HOME/jmods --add-modules java.base,java.logging --output myjre - 若需支持反射或动态代理(如 Spring 类框架),通常要加
java.desktop或java.management;纯 HTTP 服务可用java.net.http替代老式javax.net.ssl相关模块 - 排除无用模块不是靠“黑名单”,而是不写进 --add-modules ——比如桌面程序才需要
java.desktop,命令行工具完全不用,就不加 - 加
--strip-debug --compress=2可进一步减小体积(去除调试符号、压缩类文件)
验证与内存表现优化
生成后别急着打包,先验证能否真正跑起来,并观察实际内存行为:
- 用新 JRE 启动:
myjre/bin/java -XshowSettings:vm -version,确认 JVM 参数和模块加载正常 - 启动应用时加
-XX:+PrintGCDetails -Xlog:gc*(JDK 10+)看 GC 行为;精简后堆外内存(metaspace、code cache)通常下降明显 - 避免默认启用 JIT 编译器对极小应用反而拖慢冷启动:可加
-XX:+UseSerialGC -XX:TieredStopAtLevel=1强制解释执行 - 注意:jlink 输出的镜像不含
javac、jshell等开发工具,也不含src.zip或文档,这本身就是内存和磁盘节省的来源
常见误区提醒
有些“精简”操作反而引发问题:
- 不要手动删
myjre/lib/下的 .so/.dll 文件——jlink 已自动裁剪本地库,乱删会导致 JVM 启动失败 -
java.xml看似可删,但 JAXB、SAX 解析器、甚至某些日志框架内部都可能隐式依赖,删前务必测试 XML 相关功能 - 想压到几 MB?仅
java.base模块 + Serial GC + 去除调试信息,JDK 17 下可做到约 25–35 MB;再小需结合 GraalVM Native Image,已超出 jlink 范畴 - jlink 生成的是目录,不是单个 exe;要打包成 Windows 可执行文件,得配合 launch4j、jpackage 或自定义启动脚本











