未来AOT编译会取代JIT吗?

AOT 编译器变得越来越流行,尽管它们在某些领域仍然不如 JIT 编译器。然而,必须指出的是,Graal 的本机编译器尤其变得越来越复杂。

这只是一时的炒作还是JIT将来会被取代?

首先,AOT 会花费编译时间(这是昂贵且有限的开发时间),运行时性能稍差,并且会破坏与某些框架的兼容性,由于牺牲这些而换来了较短的启动时间。

快速启动时间对于自动扩展微服务和无服务器解决方案非常重要。

更重要的竞争通常是其他运行时(例如 go 和 Node),而不仅仅是 JVM 空间内的竞争。

对于受益于工作负载特定优化的代码,JIT 总是更快,因为它可以对工作负载做出动态反应。即使有 PGO,AOT 也永远是在进行“最佳猜测”。应用程序部署环境是由云供应商的计费模型驱动的,而不是实际提供最佳应用程序性能的模型,其中包括启动时间、预热、峰值性能、GC、吞吐量、延迟等所有考虑因素。

应该将更多的精力投入到 JIT 和诸如类型污染、CRaC 更快启动、AppCDS、JIT 缓存和其他技术等问题上,还有 Valhalla,它将提供大幅提高代码性能的机会。

CRaC 也可以实现更快启动:使用 JVM 通过拍摄正在运行的应用程序的快照来实现快速启动。

AOT 解决了预热时间问题,但还需要进行一些改进,如果可以使用 JIT 来解决这个问题,并获得两全其美的效果(编译时间、运行时更好的优化、快速预热)

似乎,CRaC是一个比 AOT 更有前途的解决方案,而且似乎更容易做到,而且没有 AOT 的缺点。

不过,Java的HotSpot并不是真正的JIT编译器,因为它并没有真正“及时”编译:代码被解释,然后可能被编译、优化、再次编译、取消优化等等。

与 HotSpot 相比,AOT 编译器可能会生成较差的代码,因为 AOT 编译器不支持“去优化deoptimization”,而“去优化deoptimization”是 HotSpot 最重要的功能,因为AOT是推测性优化(speculative optimization),并且可以在必要时回滚。

一个简单的例子是空指针检查:AOT 编译器必须谨慎行事并始终检查空指针,除非它可以证明这是不必要的。当 HotSpot 无法证明这一点时,它不会进行空指针检查。如果错误,则会生成 SEGV 信号,然后重写代码以包含空指针检查。

Java 的 AOT 编译器已经存在大约 20 年了,最大的区别是现在有两种免费的替代品(GraalVM 和 OpenJ9)。

Android 5 上引入了 AOT,然后由于编译时间较长,他们决定从 Android 7 开始混合使用 JIT 和 AOT。当设备处于静止状态时,每个 Android 应用程序在执行几次后都会使用 PGO 信息进行 AOT 编译。

JIT可能永远不会被取代,因为它比 AOT 编译方便得多。AOT 仅在极少数情况下(例如无服务器计算)真正表现出色,但代价是可移植性和构建复杂性增加。

使用 JIT,您甚至不必使用 javac 来运行单文件应用程序。如果没有 JIT,JShell 之类的工具也将无法使用。