作为 GraalVM 22.3 版本的一部分,甲骨文详细阐述了将两个 GraalVM 项目转移至 OpenJDK 的计划。在 2023 年的某个时间点,社区版本的即时(Just-in-time,JIT)编译器(“Graal 编译器”)和用于原生操作系统可执行文件(“原生镜像”)的提前(Ahead-of-Time,AOT)编译器的代码将会转移至一个新的 OpenJDK 项目。现有版本、GraalVM 企业版功能和其他 GraalVM 项目将保留在 GraalVM 中。
甲骨文最初在 2022 年 10 月份的 JavaOne 上宣布了这一举措,但是没有提供具体的细节。在 2022 年 12 月中旬,OpenJDK 提议新建Galahad项目来实现这次转移。
GraalVM 项目是 Oracle Labs 的一部分,因此不在 OpenJDK 的管理之下。GraalVM 目前每年有四个特性版本,遵循与 OpenJDK 不同的发布过程。
在 OpenJDK,GraalVM Java 编译器会与 Java 的发布节奏保持一致,即每年两个特性更新版本和四个补丁更新版本,每两年一个长期支持版本(Long-Term Support,LTS)。GraalVM OpenJDK 项目将使用 OpenJDK 社区流程,并提交 JDK 增强提议(JDK Enhancement Proposal,JEP),以便于将其纳入 OpenJDK Java 版本中。
Graal 编译器是使用 Java 编写的,并在 Java 运行时环境(Java Runtime Environment,JRE)中使用 Hotspot VM。它取代了使用 C++编写的 C2 JIT 编译器,大多数 Java 发行版中都包含该编译器。
GraalVM 原生镜像 AOT 编译器会生成原生可执行文件,通常来讲,与运行在 JRE 中,使用 JIT 编译器的 Java 应用相比,它们启动更快,使用的 CPU 和内存更少并且占用的磁盘空间也更小。这使得 Java 在云中更具竞争力。GraalVM 原生镜像通过删除未使用的代码并预先计算应用的堆快照实现了这些优化,在幕后它会使用 Graal 编译器。但是,这也将一些 Java 应用排除在 GraalVM 原生镜像的使用范围之外。InfoQ 最近发表了关于该话题的系列文章。
企业版提供了原生镜像性能的改进,比如用于运行时剖析的 Profile-Guided 优化,但是它不会转移到 OpenJDK 中。其他的 GraalVM 项目也不会进行转移,包括对其他语言(如 JavaScript 或 Python)的支持和 Java on Truffle(对整个 Hotspot VM 的 Java 替代方案)。
GraalVM 社区版本基于 GNU 通用公开许可证(GNU General Public License)第二版,该协议具有类路径例外(Classpath Exception)条款。许多 OpenJDK 发行版,包括甲骨文的 OpenJDK 构建版,都使用同样的许可证。而甲骨文的 Java 发行版使用的是“甲骨文免费条款和条件(Oracle No-Fee Terms and Conditions)”许可证。甲骨文宣布,“从许可证的角度来看,所有的 GraalVM 技术都与 Java 一致[......]",并承诺“在未来几个月内提供更多的细节”。
GraalVM 22.3 发布,支持 JDK 19 并改善了可观测性
GraalVM 22.3 是2022年最后一个特性发布版本。它对 JDK 19 提供了实验性的支持,包括来自 Loom 项目的虚拟线程和结构化并发。对 JDK 19 的完整支持会在 2023 年 1 月底的 GraalVM 23.0 中提供。
该版本包含了原生可执行文件监控方面的大量改进,这是一个落后于在 JRE 中运行 Java 程序的领域。JDK 工具jvmstat
现在可以监控原生可执行文件的性能和资源使用,并收集堆转储,以便于使用 VisualVM 进行探查。原生可执行文件还可以为免费的 Java Flight Recorder(JFR)工具记录JavaMonitorEnter
、 JavaMonitorWait
和ThreadSleep
事件。
GraalVM 原生镜像编译器需要所谓的 hint,以获取 Java 代码中对反射的使用。与 Spring 和 Micronaut 框架协作,GraalVM 在 2022 年 7 月推出了一个面向 Java 库 hint 的公共仓库。这个名为“GraalVM Reachability Metadata”的仓库现在已经包含了针对 Hibernate、Jetty、JAXB 和 Thymeleaf 的条目。
GraalVM 原生镜像 AOT 编译器在选定的基准测试上要快 2 到 3 倍。原生可执行文件运行时需要更少的内存,运行整数的最小/最大操作的操作要更快。在 22.2 中添加了两个实验性的优化,StripMineCountedLoops
和EarlyGVN
,它们现在已经稳定并默认启用。
原生可执行文件现在可以包含软件物料清单(Software Bill of Material,SBOM),并且通过更好地识别内存使用和内存泄露,调试体验得到了改善。
在 GraalVM 生态系统的新闻中,当前 IntelliJ 2022.3 版本提供了调试原生可执行文件的实验性支持,JUnit 5.9.1 也提供了注解包含或排除它们。
GraalVM 中的 Python 实现改名为 GraalPy。它在兼容性和性能方面有很多改善,就像 Ruby 的实现 TruffleRuby 一样。GraalVM 中的 Python 和其他语言得益于 Windows 上 LLVM 运行时的实验性可用性。
该 GraalVM 版本通过一行 shell 脚本为 macOS 和 Windows 提供了新的下载方案:
Leyden 项目通过 Condenser 优化 Java
Leyden项目是 OpenJDK 的一项倡议,其使命是“改善 Java 程序的启动时间、达到性能峰值的时间和占用空间”。甲骨文澄清了 GraalVM 与该项目的关系:它“计划在 OpenJDK 社区中发展原生镜像技术,以跟踪 Leyden 项目的规范”。Leyden 项目最初的目标是在 Java 语言规范中增加原生可执行文件,比如 GraalVM 原生镜像 AOT 编译器产生的可执行文件。在 2020 年 6 月正式创建后,该项目在两年内没有任何公开活动。
在 2022 年 5 月,Leyden 项目再次出现并带来了第二个目标:对于在带有 JIT 编译器的 JRE 上运行的 Java 应用,为它们识别和实现广泛的优化。它之所以这样做,是因为 GraalVM AOT 编译器有一个强制的封闭性假设,也就是在构建时必须具有应用的所有信息,比如它的类和资源。有些 Java 应用和库使用了 Java 中的动态特性,这些特性在该限制下无法正常运行。第二个目标的一些优化需要对 Java 语言规范进行一些修改。它的实现将依赖于现有的工具,比如 Hotspot VM 和 jlink 工具。
2022 年 10 月,Leyden 项目详细介绍了如何实现这两个目标。它引入了在编译时和运行时之间运行的 condenser 的概念。它能够“将程序转变为一个新的、更快的、可能更小的程序,同时保留原程序的含义”。Java 语言规范将进行改进,以包含 condenser。
Condenser 将会定义 AOT 编译和原生可执行文件如何适应 Java,以实现 Leyen 项目最初的目标。但是 condenser 还会改善在带有 JIT 编译器的 JRE 中运行的 Java 应用,以服务于第二个目标。GraalVM Java 编译器、JRE 和 HotSpot JIT 编译器将继续获得独立于 Leyden 项目的特性和升级。所以,condenser 提供了一个额外的优化层。
截止 2022 年 12 月份,condenser 的开发尚未开始。这使得 Leyden 不太可能在 2023 年 9 月份发布的下一个 Java LTS 版本中交付 condenser。所以,有 Leyden 项目成果的最早的 Java LTS 版本可能是 2025 年 9 月的 Java 25。
Java 社区对甲骨文转移 GraalVM 的反应
Spring Boot 刚刚在 2022 年 11 月发布了 3.0 版本,Spring Boot 加入了在生产环境中支持 GraalVM 原生镜像 AOT 编译的Java框架大家庭,其他框架还包括 Quarkus、Micronaut 和 Helidon。InfoQ 就甲骨文的公告采访了这四个框架的代表。
第一个回应来自 Red Hat Java 团队的卓越工程师Andrew Dinn,以及 Red Hat 的首席软件工程师Dan Heidinga。2022 年 5 月他们在InfoQ发表过文章,主张 OpenJDK 和 GraalVM 之间要更加紧密地结合。
InfoQ:你们在 2022 年 5 月份的文章中提到,“原生 Java 需要纳入到 OpenJDK 中,以实现与其他正在进行中的功能增强的共同演进”。从这个角度来讲,你们是如何看待甲骨文的声明的?
Andrew Dinn & Dan Heidinga:我们对甲骨文的声明和 Leyden 项目最近的进展都持非常乐观的态度。将 GraalVM 的关键部分,即 JIT 编译器和原生镜像,纳入 OpenJDK 项目,有助于将它们的开发和用户社区更好地结合在一起。
在 OpenJDK 项目下,采用共同的开发模型以及现有的 OpenJDK 管理方式,能够让 GraalVM 开发人员与更广泛的 OpenJDK 社区进行更好的沟通和协作。而且,这能够让这些组件更容易地影响其他 Java 项目的设计,如 Valhalla 或 Amber,使它们更适应 AOT 编译。
最后,它将 GraalVM 直接纳入 Java 规范流程的管理之下,并确保 Java 和 GraalVM 在相同的方向上共同发展。
InfoQ:甲骨文还宣布,GraalVM 原生镜像 AOT 编译器将会实现 OpenJDK 中 Leyden 项目的规范。Leyden 最近推迟了原生 Java 的标准化,而选择了优化 JIT 编译。鉴于新的进展,你们如何看待这个决策?
Dinn & Heidinga:Leyden 项目最近提出了针对 Mark Reinhold 关于如何解决这个问题的设想。他建议使用 Condenser,将计算从应用的一个阶段转移至另外一个阶段。同时,他还提出了支持该方式所需的规范变更(为了提供一个稳定的基础,这是必要的任务)和 Java 语言的变更,比如惰性静态JEP草案。
这些都没有提及“延迟 AOT”或“优化 JIT”。这种方式使 AOT 和 JIT,甚至通常的执行方式,都会得到优化。他的样例使用的是一个 XML 库,在运行时读取配置文件。这种转移计算的方式对 AOT 和 JIT 都有益。正如我们在像 Quarkus 这样的框架中看到的,在构建时初始化状态对快速启动至关重要。
Leyden 现在正在奠定基础,在保留程序含义的基础上进行预初始化,这是我和 Andrew 在文章中提出的关键需求之一。
这不仅仅是确保 GraalVM 与 Java 规范之间紧密且可靠地协作的问题。Mark 的提案明确指出,Leyden 项目如果需要的话,也需要谨慎而连贯地更新规范,以允许特定 Condensation 步骤的行为变化。例如,它甚至提到当面向完全封闭的 AOT 程序时,需要明确类加载器行为的语义。
将 GraalVM 纳入 OpenJDK 也会使来自这两个项目的代码混合和匹配更容易。也许,GraalVM 的原生镜像 AOT 编译器会成为程序转换流水线中的最后 condenser。
InfoQ:你们的文章中描述了在原生 Java 中无法使用的 Java 特性。对可观测性至关重要的 Java Agent 的支持是另一个缺失的特性。对于这些限制,GraalVM 应该怎么做呢?
Dinn & Heidinga:GraalVM 团队可能在未来一年左右的时间内忙于将他们的代码迁移至 OpenJDK。项目的迁移往往会比预期地更长,即便他们提前有所预期也在所难免。
我们看到 GraalVM 社区正在致力于增加可用于原生镜像的工具,包括 Red Hat 为支持 JFR 和 JMX 所做的努力,以及在调试支持方面的工作,包括 Red Hat 和 IntelliJ 的努力,所有这些都是与甲骨文的开发人员一起进行的。
GraalVM 处在一个很好的位置,可以继续演进并与现有的代理供应商合作,为原生镜像寻找合适的插装(instrumentation) API。在这个过程中,学到的所有内容都能直接用于 Leyden,并加速 Leyden 的交付。
这就是现在的终极目标:将所有的经验和学习到的东西(希望还会有些代码)输入到 Leyden 的开发过程中,以帮助该项目交付所需的规范更新、语言变更和 condenser 工具,以推进整个框架、库和应用的广泛采用。
Sébastien Deleuze是来自 VMware 的 Spring 框架提交者,分享了 Spring 生态系统的观点。
InfoQ:你们如何看待 Java 的 GraalVM JIT 和 AOT 编译器转移至 OpenJDK 这一事件的?
Sébastien Deleuze:从将 Spring 应用编译成原生可执行文件开始,我们就与 GraalVM 团队进行了非常紧密的合作。我们的目标是限制“原生 Java”和“JVM 上的 Java”之间的差异,同时保持 AOT 方式所带来的效率收益。所以,从我们的角度来看,GraalVM JIT 和 AOT 编译器转移到 OpenJDK 是个好消息,因为这是在 OpenJDK 的旗帜下实现更统一的 Java 的关键一步,即便在原生 Java 和 JVM 之间还存在一些差异。
我们也到了这样一个节点,那就是越来越多的问题或优化需要 OpenJDK 代码库进行一些变更。所以,希望 GraalVM 在 OpenJDK 方面能够获得一些帮助,包括与 Leyden 项目更紧密的合作。
一直以来,GraalVM 都是一个包含多个子项目的伞状项目,比如多语言(polyglot)技术,有着不同的成熟度和不同的适用场景。将转移到 OpenJDK 内容与其他内容区分开来,有助于更加专注于 GraalVM 原生镜像的支持,并明确 GraalVM 对终端用户的意义。
InfoQ:目前,GraalVM 的 Java 编译器每年有四个特性版本,未来将有两个。这对 Spring 有什么影响吗?
Deleuze:的确,在我们试验 Spring Native 项目的时候,每年四个特性版本对于快速推进工作是相当有用的。但是,2022 年 11 月底我们发布了 Spring Boot 3,从此开始了对 GraalVM 原生的正式和生产级别的支持。因此,从这个角度看,GraalVM 的特性发布节奏变慢并与 OpenJDK 的发布保持同步,将有助于一致地处理这些升级,减少出现频繁破坏性变更的风险,并且能够让我们有更多的时间从事长远的新特性。不要忘了,可以预测的是每年还会有四个季度性的关键补丁更新,以修补原生镜像支持方面的问题。
InfoQ:GraalVM Java 编译器的开发将会有所不同,至少会有一个 OpenJDK 项目,另外还涉及提交者、审校者和 JEP,这对 Spring 会有什么影响吗?
Deleuze:尽管流程会有所变化,但我们希望能够继续保持 Spring 与 OpenJDK 方面 GraalVM 团队的合作。同时,正如之前宣布的,我们与 BellSoft(OpenJDK 的主要贡献者之一)在 JDK 和原生支持方面保持着密切合作。在未来的几个月内,我们会分享关于该影响的更多细节。
Red Hat 的卓越工程师和主管Jason Greene代表 Quarkus 框架做出了回应。
InfoQ:你们如何看待 Java 的 GraalVM JIT 和 AOT 编译器转移至 OpenJDK 这一事件的?
Jason Greene:我们认为这对 GraalVM 和 OpenJDK 社区都是一个积极的变化。这两个项目更紧密地联系在一起,将会增加双方的合作和代码共享,包括推进 Leyden 项目的工作。我们与这两个团队都有良好的关系,并期待着在新的结构中继续保持这种关系。
InfoQ: 目前,GraalVM 的 Java 编译器每年有四个特性版本,未来将有两个。这对 Quarkus 有什么影响吗?
Greene: 这种变化可能意味着需要等待更长的时间才能在 GraalVM 的正式版本中出现原生镜像相关的新特性。但是,GraalVM 也有一个扩展性的 SPI,我们目前在 Quarkus 中使用了他。它与 Quarkus 本身相关的改善相结合,能够在频繁的 Quarkus 发布计划中改进 Quarkus GraalVM 原生镜像的体验。
InfoQ:GraalVM Java 编译器的开发将会有所不同,至少会有一个 OpenJDK 项目,另外还涉及提交者、审校者和 JEP,这对 Quarkus 会有什么影响吗?
Greene:我们预计这些变化对 Quarkus 社区的影响很小。即使 OpenJDK 的流程和工具有一些差异,但它们与当前的模式有着相似的目标。虽然 GraalVM 没有使用 JEP,但是它们有关于 issue 相关的设计讨论,并且具有包含代码审查的 PR 过程。
甲骨文的架构师Graeme Rocher提供了来自 Micronaut 框架的观点。
InfoQ:你们如何看待 Java 的 GraalVM JIT 和 AOT 编译器转移至 OpenJDK 这一事件的?
Graeme Rocher:对于社区和 GraalVM 的广泛采用来讲,这是非常好的一个举措。
InfoQ:目前,GraalVM 的 Java 编译器每年有四个特性版本,未来将有两个。这对 Micronaut 有什么影响吗?
Rocher:在 GraalVM 的早期采用阶段,每季度一次的发布节奏很有帮助。现在 GraalVM 已经很成熟和稳定了,所以在这个阶段,转为每年发布两个版本已经没有什么问题了,这更像是一件好事。
Micronaut 团队和 GraalVM 团队都在 Oracle Labs 工作,并将继续合作,确保每次发布的开发者构建和快照版本都经过良好的测试。
InfoQ:GraalVM Java 编译器的开发将会有所不同,至少会有一个 OpenJDK 项目,另外还涉及提交者、审校者和 JEP,这对 Micronaut 会有什么影响吗?
Rocher:毫无疑问,这会努力使 AOT 的众多 API 和注解实现标准化,随着这些新 API 的出现,我们会转而使用它们。然而,这对 Micronaut 来说并不是一个新的挑战,因为它已经与 GraalVM 同步发展,并在它们出现时适配了这些改进。
甲骨文的架构师Tomas Langer代表 Helidon 框架做出了回应。
InfoQ:你们如何看待 Java 的 GraalVM JIT 和 AOT 编译器转移至 OpenJDK 这一事件的?
Tomas Langer:JIT 编译器会对运行时提供帮助,对 Helidon 的源代码和开发过程没有影响。对 OpenJDK 的任何性能改进都是非常棒的!
AOT 编译会影响我们设计(和测试软件的方法)。如果原生镜像成为 OpenJDK 的一部分,那么与 AOT 相关工作的复杂性都会降低,我们只需要安装一个 JDK 即可。对于我们的客户来讲也是如此。
InfoQ:目前,GraalVM 的 Java 编译器每年有四个特性版本,未来将有两个。这对 Helidon 有什么影响吗?
Langer:随着 GraalVM 原生镜像变得越来越成熟,我们应该不会看到像过去那样的重大变化。减少发布版本实际上会使我们更加轻松,因为我们应该比以往更容易支持最新的版本,实际上,我们正在跳过对 GraalVM 一些发布版本的支持,因为大量的测试和相关工作使我们难以保持对最新版本的支持。
InfoQ:GraalVM Java 编译器的开发将会有所不同,至少会有一个 OpenJDK 项目,另外还涉及提交者、审校者和 JEP,这对 Helidon 会有什么影响吗?
Langer:我想答案和前面的很相似,GralVM 原生镜像越成熟,我们应该越容易使用它。
目前,GraalVM 计划在2023年发布四个特性版本。至少第一个版本仍将包含 GraalVM 的 Java 编译器,因为 GraalVM 原生镜像将在 2023 年 1 月 24 日发布的 23.0 版本中获得对 Java 19 的完整支持。现在,还不清楚 GraalVM 的 Java 编译器何时会在 GraalVM 中进行最后一次发布,何时会在 OpenJDK 中进行第一次发布。
作者简介:
Karsten Silz 在欧洲和美国作为全栈 Java 开发者(Spring Boot、Angular、Flutter)工作了 23 年。2004 年,他在美国共同创办了一家软件产品创业公司。Karsten 领导了 13 年的产品开发,在公司成功出售后离任。自 2003 年以来,他也曾作为承包商工作。2020 年,他作为首席技术官在英国共同创立了 SaaS 初创公司“Your Home in Good Hands”。
原文链接:
GraalVM Java Compilers Join OpenJDK in 2023, Align with OpenJDK Releases and Processes
相关阅读:
OpenJDK提议Galahad项目合并GraalVM的原生编译
Spring Boot 3和Spring Framework 6使用Java 17和Jakarta EE 9,并支持基于GraalVM的原生Java
评论 2 条评论