jlink精简jre
jdk9以后提供了模块化方案,利用此方案可以实现jre的精简。但是我在实现过程中遇到了很多问题
环境
- oracleJdk11
- maven3.6.1
- Idea2020.1.1
情况概述
我创建了三个模块model、service、entry,相互之间依赖关系如下

其中slf4j.api是service模块中引入的第三方依赖
将三个模块打包后,找到生成的jar文件,将三个jar放在同一个文件夹中。
然后执行命令
1 | |
其中:
- /Users/apple/resource/project/java/jdk11/target/ 代表放置了三个jar的文件夹目录
- /Library/Java/JavaVirtualMachines/jdk-11.0.7.jdk/Contents/Home/jmods jdk的模块目录
- –add-modules jdk11.entry 启动模块,这个模块内有main方法
- –launcher entry=jdk11.entry/cn.inkroom.entry.Enry 启动方法,等号前内容随便写
第一次执行结果如下:
1 | |
推测是因为引入了第三方依赖,但是找不到。因此找到项目中的第三方依赖的jar,放到和之前的三个jar相同的目录中。
再次执行命令如下:
1 | |
这里错误就比较麻烦了。意思是jlink只支持命名模块,不支持自动模块。真的不理解java社区的思路,不支持自动模块,那生态里的一大堆jar都等着别人升级到jdk11?这个jlink搞得还有多大意义
经过我百般搜索,最终找到一篇博客
总体思路是通过插件给自动模块补充module-info.java,但是这会有非常多的问题。
以我这里用的slf4j举例,slf4j因为其实现原理的原因,其jar实际上是不太完整的,缺少了一些实现类,因此在生成module-info时,需要补上具体实现了slf4j的依赖。
然后在打包的过程中,插件就会下载这些相关依赖,非常耗时。
当然,耗时其实影响不大。真正影响大的是需要给所有的自动模块补充module-info,换句话说,本来应该给类库维护者的工作给加到自己身上,如果项目中用到的依赖较多,这个工作量非常大;而且由于不同类库的实现不同,还可能出现类似slf4j这种必须了解其实现细节才能补充的情况。
总结
就目前的情况来看,jlink实在是一个鸡肋。
首先就普通web项目来说,精简jre并没有什么意义,不差那点空间;而且假设一台机器上要部署多个不同的服务,多个jre只会让维护混乱。
其次,目前大多数类库都没有实现模块化,导致jlink无法向下分析,也拆不出合适的模块。