Leyden项目推迟了OpenJDK AOT编译器,并优化了JIT编译器
Project Leyden的目标是 "解决Java启动时间慢、达到性能峰值的时间慢和占用空间大的长期痛点"。它想通过在OpenJDK中 "引入静态图像的概念 "来实现这一目标。静态图像来自于对本地可执行文件的时间提前(AOT)编译。在两年没有公开可见的活动之后,莱顿项目在2022年5月转向,首先优化即时编译(JIT)。由此产生的优化几乎肯定比最初的计划要弱,最早也要在2025年底才能到达主流Java开发者手中。甲骨文公司的Graal项目已经实现了Project Leyden的目标,但代价是该项目目前想避免的。
Graal项目起源于甲骨文实验室,不是OpenJDK的一部分。它的GraalVM Native Image是一个Java AOT编译器,今天可以产生本地可执行文件。与Java的JIT编译器相比,它们有四个优势:快速启动、较低的内存和CPU使用率、较少的安全漏洞和较小的文件大小。
但这些成就是有代价的。GraalVM Native Image在Java应用程序上执行了一个所谓的封闭世界的假设,这消除了一整类Java应用程序。为什么呢?因为Java是一种动态语言,在运行时赋予应用程序很多权力,如反射、类加载、甚至类构造。而其中一些功能在GraalVM Native Image的封闭世界里是行不通的。这就是为什么Project Leyden现在想 "探索比封闭世界约束更弱的一系列约束,并发现它们能带来哪些优化。"尽管如此,Leyden "很可能[......]产生完全静态的图像",尽管只是 "从长远来看"。
OpenJDK以前曾尝试过AOT编译
Project Leyden是OpenJDK对AOT编译的第二次尝试。第一次尝试是 **jaotc**JEP 295,Ahead-of-Time Compilation,于2017年9月在JDK 9中交付。与GraalVM Native Image一样,它使用了Graal项目。与GraalVM Native Image不同,它非常不受欢迎。当甲骨文从其Java 16构建中删除jaotc ,"没有人抱怨,"甲骨文在JEP 410中急切地指出,删除实验性AOT和JIT编译器,在JDK 17中交付。
对于OpenJDK项目来说,Leyden项目有一段不寻常的历史。Java语言架构师Mark Reinhold在2020年4月提出了这个项目,随后OpenJDK在2020年6月将其批准为一个项目。但从批准到2022年5月创建邮件列表的两年时间里,该项目没有显示出明显的进展。这就是为什么该项目刚刚开始,现在关注的是"概念而不是代码"。Reinhold表示,诸如 "HotSpot JVM、C2编译器、应用程序类数据共享(CDS)和 **jlink**连接工具 "是优化的目标。值得注意的是,该列表中缺少CRaC,这是一个OpenJDK项目,通过从磁盘加载Java应用状态来减少启动时间。
一个信封式的计算显示了可能的交付日期。现在,LTS版本在Java中的重要性已经超过了。前监测公司New Relic的Ben Evans在2022年Devoxx UK上宣布,"没有一个非LTS版本的市场份额超过1%"。这表明,主流的Java开发者只从一个Java LTS版本迁移到另一个LTS版本。
由于Leyden项目现在才开始进行,在2023年9月JDK 21,也就是下一个LTS版本中,很少有成果可以投入生产。因此,主流Java开发者可能只有在2025年9月的LTS版本(JDK 25)中才能看到Leyden项目的第一批成果。基于这一假设,Leyden项目最早会在2027年9月通过JDK 29向本地可执行文件提供AOT编译。InfoQ将继续关注Leyden项目的进展。
Spring Boot对Project Leyden的反应
至少莱顿项目考虑的一些功能,如 **jlink**或CRaC,都需要应用程序框架的支持才能发挥出最佳效果。这就是为什么InfoQ联系了代表Spring Boot、Quarkus和Micronaut的开发者,询问他们对Project Leyden公告的初步反应。
Spring Framework项目负责人Juergen Hoeller对Project Leyden表示赞同:
Leyden项目是一个很有前途的举措,与我们在Spring Framework 6和Spring Boot 3中的大方向一致。
Hoeller也支持CRaC for Spring:
CRaC堆快照可以成为改善基于Spring的应用程序的启动时间的一个常见选项。在应用启动阶段的最后阶段进行快照,这时几乎没有任何开放的文件或网络资源,这与CRaC的预期一致。Spring甚至已经在应用上下文刷新结束时重置了它的公共缓存,在用请求相关的元数据动态地重新填充缓存之前清除了启动相关的元数据。就[......]应用上下文对快照事件的具体反应或改进通用组件的 "snapsafety "而言,我们肯定会在技术上可行的情况下,在Spring Framework 6.x产品线中尝试赋予早期采用者权力。
Hoeller认为,Spring将支持 jlink和Java平台模块系统(JPMS)不久:
目前Spring Framework 6.0的里程碑还不包括模块信息描述符。这是9月份M6里程碑的路线图,在我们进入6.0候选发布阶段时,重新评估第三方生态系统的模块系统准备情况。随着莱顿项目有可能变成 **
jlink**变成一个更强大、更全面的工具,我们不仅要为当前的能力做准备,还要为它的进一步发展做准备。**jlink**'s目前的能力,也为它的进一步发展做准备。
Quarkus对Project Leyden的反应
Quarkus联合创始人兼联合负责人Jason Greene对Project Leyden发表了看法:
我们对Leyden项目修改Java语言规范以更好地支持静态图像、本地编译和其他技术(如JVM检查点)的目标感到非常兴奋。此外,我们很高兴看到封闭世界仍然是该项目可能的长期目标。
Greene接受了Quarkus的CRaC:
CRaC研究项目的最初支持最近由CRaC负责人贡献给Quarkus项目。由于Quarkus无论在运行时的目标类型上都会进行构建时的优化,所以在OpenJDK上运行时,你仍然可以看到相当大的节省,而不仅仅是GraalVM。在OpenJDK之上添加检查点方法,如CRaC,可以进一步优化启动时间。它并没有带来类似于本地图像的内存节省,但对于喜欢或需要JVM执行的应用程序来说,它是一个有趣的未来选择。
然而,Greene对 **jlink**和JPMS的Quarkus:
截止到今天。 **
jlink**只给基于JVM的应用程序的存储开销带来好处(没有它,内存开销和启动时间基本上是一样的)。然而,在容器或Kubernetes应用程序中,常见的做法是在标准的JVM基础镜像上分层,这已经比将所有应用程序切换到jlink(因为每个人都会捆绑自己的修剪过的JVM)。在本地镜像的情况下,JVM的细粒度元素被编译到镜像中,所以 **jlink**在这种情况下也是没有帮助的。同样,对于JPMS,Quarkus已经通过Quarkus扩展有了模块化的概念,允许你将你的依赖集修剪成你需要的东西。Quarkus采取的方法与大多数Java生态系统和构建工具今天所喜欢的简单的平面classpath兼容。在成本方面,移动到一个纯粹的JPMS模块模型作为 **jlink**要求(没有自动模块),这意味着不仅对Quarkus,而且对Quarkus构建的许多库都是一种突破性的改变。在考虑转换之前,我们希望看到这些因素能够更好地平衡。
Micronaut对Leyden项目的反应
Object Computing, Inc.(OCI)的首席软件工程师Sergio del Amo Caballero对Project Leyden没有Micronaut框架的官方声明。但他指出最近GitHub上有一个关于在Micronaut中添加CRaC支持的问题。
Caballero还分享了2020年7月的一段YouTube视频,其中Micronaut的创建者Graeme Rocher对JPMS进行了评论:Micronaut支持JPMS并发布了模块信息文件,但必须 "在支持Java 8之间取得平衡"。JPMS是在Java 9中加入的,但Micronaut 3.5,即当前版本,仍然运行在Java 8上。
结论
到目前为止,OpenJDK还没有解决 "Java启动时间慢、达到性能峰值的时间慢、占用空间大等长期痛点"。首先,它的 jaotc首先,它的AOT编译器未能获得吸引力,并被退役了。然后,Project Leyden项目开始对Java的本地编译进行标准化,但停滞了两年之久。
现在,Project Leyen已经转向首先优化JIT编译,事情正在向好的方面发展。Spring和Quarkus都接受了CRaC来减少启动时间。但是当涉及到较小的Java应用规模时,只有Micronaut坚持Project Leyden的建议,使用JPMS。Spring计划在2022年底前在第6版中支持JPMS,尽管Spring生态系统可能不会。而Quarkus目前没有计划加入JPMS。
Leyden项目的成果,以JEP的形式,最早可以在2025年底到达主流Java开发者手中。因此,至少在那之前,将GraalVM Native Image AOT编译器与Quarkus、Micronaut或即将推出的Spring Boot 3等框架结合起来,仍然是避免 "Java缓慢的启动时间、缓慢的性能峰值时间和庞大的足迹 "的最佳选择。