jlink精简jre

jdk9以后提供了模块化方案,利用此方案可以实现jre的精简。但是我在实现过程中遇到了很多问题

环境

  • oracleJdk11
  • maven3.6.1
  • Idea2020.1.1

情况概述

我创建了三个模块modelserviceentry,相互之间依赖关系如下

165608FC-ACAA-438A-8184-645423DE2621.png

其中slf4j.apiservice模块中引入的第三方依赖


将三个模块打包后,找到生成的jar文件,将三个jar放在同一个文件夹中。

然后执行命令

1
./jlink -p /Users/apple/resource/project/java/jdk11/target/:/Library/Java/JavaVirtualMachines/jdk-11.0.7.jdk/Contents/Home/jmods --add-modules jdk11.entry --output /Users/apple/resource/project/java/jdk11/target --launcher entry=jdk11.entry/cn.inkroom.entry.Enry

其中:

  • /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
错误: Module slf4j.api not found, required by jdk11.service

推测是因为引入了第三方依赖,但是找不到。因此找到项目中的第三方依赖的jar,放到和之前的三个jar相同的目录中。


再次执行命令如下:

1
错误: 自动模块不能用于来自 file:///Users/apple/resource/project/java/jdk11/target/logback-core-1.2.3.jar 的 jlink: logback.core

这里错误就比较麻烦了。意思是jlink只支持命名模块,不支持自动模块。真的不理解java社区的思路,不支持自动模块,那生态里的一大堆jar都等着别人升级到jdk11?这个jlink搞得还有多大意义


经过我百般搜索,最终找到一篇博客

总体思路是通过插件给自动模块补充module-info.java,但是这会有非常多的问题。

以我这里用的slf4j举例,slf4j因为其实现原理的原因,其jar实际上是不太完整的,缺少了一些实现类,因此在生成module-info时,需要补上具体实现了slf4j的依赖。

然后在打包的过程中,插件就会下载这些相关依赖,非常耗时。

当然,耗时其实影响不大。真正影响大的是需要给所有的自动模块补充module-info,换句话说,本来应该给类库维护者的工作给加到自己身上,如果项目中用到的依赖较多,这个工作量非常大;而且由于不同类库的实现不同,还可能出现类似slf4j这种必须了解其实现细节才能补充的情况。

总结

就目前的情况来看,jlink实在是一个鸡肋。

首先就普通web项目来说,精简jre并没有什么意义,不差那点空间;而且假设一台机器上要部署多个不同的服务,多个jre只会让维护混乱。

其次,目前大多数类库都没有实现模块化,导致jlink无法向下分析,也拆不出合适的模块。


jlink精简jre
http://blog.inkroom.cn/2020/09/24/1SHCBJP.html
作者
inkbox
发布于
2020年9月24日
许可协议