字节码转化为机器码的发展历程

198 阅读2分钟

字节码到机器码的转化环节共经历了三个发展阶段,分别是解释执行阶段、解释执行 + 编译执行阶段、提前编译阶段。

解释执行(Interpreter Execution)

解释执行就是将编译好的字节码一行一行地翻译成机器码执行。这种模式在 JVM 的早期版本中就已经存在了,它舍弃了编译时间,只在程序运行时把字节码实时翻译为机器代码。在解释执行过程中,由于每次都需要重新解释字节码,相同的字节码会存在被反复多次翻译执行的情况,所以采用这种模式的程序运行性能一般比较低。为此,JVM 在解释执行的基础上引入了即时编译执行技术。

即时编译(Just in Time Compilation)

即时编译也就是我们常说的 JIT,以方法为单位,即时编译将字节码一次性翻译为机器码后再执行。JIT 编译器从 JDK 1.1 版本开始引入。通过这种技术,JVM 就可以发现某段字节码被反复执行,从而启动 JIT 编译器,把这段字节码编译成机器代码,提高运行速度。这种方式虽然会根据运行时机器的实时状态,比如内存状态等,生成最优的机器代码,但是它也需要占用额外的内存空间,并与运行时的程序竞争 CPU 资源。并且需要在系统运行一段时间后才能达到运行时的性能巅峰。这就像你刚刚入职一家公司,需要有一个了解的过程,熟悉之后,才能达到最佳的工作状态。但是这与云原生时代系统启动即性能巅峰的要求是有出入的。所以虽然主流的 JVM 依然是采用解释执行 + 编译执行的混合模式,但是更符合云原生要求的提前编译模式已经开始崭露头角。

提前编译(Ahead of Time Compilation)

提前编译也就是我们常说的 AOT。AOT 编译器是从 JDK 1.9 开始引入的 JEP 295 规范。与 JIT 编译器不同,AOT 是在程序运行前就把字节码编译成了机器码。使用 AOT 编译器的优势在于你可以在部署应用程序前编译代码,而不是在运行时才编译,这可以减少应用程序启动时和运行时需要的 CPU 资源,优化资源的使用方式,减少启动延迟时间,提高性能。

此文章为11月Day12学习笔记,内容来源于极客时间《云时代的 JVM 原理与实战》,强烈推荐该课程