新一代即时编译器
对需要长时间运行的应用来说,由于经过充分预热,热点代码会被 HotSpot 的探测机制准确定位捕获,并将其编译为物理硬件可直接执行的机器码,在这类应用中 Java 的运行效率很大程度上是取决于即时编译器所输出的代码质量。
HotSpot 虚拟机中包含有两个即时编译器,分别是编译时间较短但输出代码优化程度较低的客户端编译器(简称为 C1)以及编译耗时长但输出代码优化质量也更高的服务端编译器(简称为 C2),通常它们会在分层编译机制下与解释器互相配合来共同构成 HotSpot 虚拟机的执行子系统的。
自 JDK 10 起,HotSpot 中又加入了一个全新的即时编译器:Graal 编译器,看名字就可以联想到它是来自于前一节提到的 Graal VM。Graal 编译器是作为 C2 编译器替代者的角色登场的。C2 的历史已经非常长了,可以追溯到 Cliff Click 大神读博士期间的作品,这个由 C++写成的编译器尽管目前依然效果拔群,但已经复杂到连 Cliff Click 本人都不愿意继续维护的程度。而 Graal 编译器本身就是由 Java 语言写成,实现时又刻意与 C2 采用了同一种名为“Sea-of-Nodes”的高级中间表示(High IR)形式,使其能够更容易借鉴 C2 的优点。Graal 编译器比 C2 编译器晚了足足二十年面世,有着极其充沛的后发优势,在保持能输出相近质量的编译代码的同时,开发效率和扩展性上都要显著优于 C2 编译器,这决定了 C2 编译器中优秀的代码优化技术可以轻易地移植到 Graal 编译器上,但是反过来 Graal 编译器中行之有效的优化在 C2 编译器里实现起来则异常艰难。这种情况下,Graal 的编译效果短短几年间迅速追平了 C2,甚至某些测试项中开始逐渐反超 C2 编译器。Graal 能够做比 C2 更加复杂的优化,如“部分逃逸分析”(Partial Escape Analysis),也拥有比 C2 更容易使用“激进预测性优化”(Aggressive Speculative Optimization)的策略,支持自定义的预测性假设等等。
今天的 Graal 编译器尚且年幼,还未经过足够多的实践验证,所以仍然带着“实验状态”的标签,需要用开关参数去激活,这让笔者不禁联想起 JDK 1.3 时代,HotSpot 虚拟机刚刚横空出世时的场景,同样也是需要用开关激活,也是作为 Classic 虚拟机的替代品的一段历史。
Graal 编译器未来的前途可期,作为 Java 虚拟机执行代码的最新引擎,它的持续改进,会同时为 HotSpot 与 Graal VM 注入更快更强的驱动力。