理解Java的JIT和AOT

Posted 整码阁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解Java的JIT和AOT相关的知识,希望对你有一定的参考价值。

1. JIT和AOT是什么?

JIT是Just-In-Time的首字母缩写,指程序运行期间发生的编译行为。

  • JIT多伴随解释器,因为解释型语言是按行解释执行,JIT将“常用”功能编译为机器码,需要时直接执行,减少解释时间;
  • 例如:Python(pypy),新版javascript、Ruby、php解释器;

AOT是Ahead-Of-Time的首字母缩写,指程序运行之前发生的编译行为。

  • 对于编译型语言,AOT啥也不是,本身就是先编译后执行,但对于解释型语言,AOT提前“预见”热点功能,并编译为机器码,同样减少解释时间;
  • 例如:C,C++,Rust,Go,Java AOT;

2. Java的JIT和AOT是什么?

下面两张图来自Mark Stoodly的分享,清晰解释了Java JIT和AOT的位置和作用。可以看出JIT是在代码执行中“理解”代码的过程,而AOT是在代码执行前“预见”代码的过程。


JIT位置


AOT位置

3. Java的JIT和AOT如何执行?

下图是简化的JVM执行流程图,包含三个操作。


1. 第一个操作是JVM的标准动作:JVM解释器(一行一行的)读取字节码并执行。

2. 第二个操作是Java JIT:从字节码中“寻找”热点代码编译为机器码,放入代码缓存,下次调用跳过解释器,直接执行该机器码。

  • JIT包括C1和C2两种编译器,目的相同但深度不同;
  • C1编译器:寻找高频(>10000次)字节码编译为机器码。C1速度快但优化有限,也叫客户端优化;
  • C2编译器:通过code profiling数据,定位code path进而寻找热点代码(Hot Spot,名字很熟悉是不是?),对这部分字节码进行深度优化,编译为机器码。C2速度慢但深度优化,执行速度快,也叫服务器端优化;
  • C2包含二十多项优化,包括 死代码(删除没有使用的代码)、 逃逸分析(方法中创建但没有返回的对象,将它从堆移到栈)、 方法对齐(将大量小方法移到到调用方法中)、 锁删除(如果只有一个线程使用锁,删除该锁)、 Null检查(如果对象永远不为null,删除判空);
  • C1和C2都在后台运行,只是时间不同。当字节码解释时C1开始运行,优化后替换字节码调用;当C1代码运行时C2开始运行,优化后替换C1代码调用;
  • Java 7及以前可以通过参数--client或--server自定义C1或C2,Java 8默认启用C1和C2;

3. 第三个操作是Java AOT:先将部分字节码(class文件/文件夹/JAR包)提前编译为机器代码库,然后再启动程序,减少字节码解释。

  • AOT可以加快代码执行,但缺点也很明显。因为Java字节码独立于平台,但机器码依赖平台架构,且目前AOT支持的平台有限。同一份代码,如果要在ARM和X86运行,则需要AOT两份;
  • jaotc是JDK 9引入的实验性命令,在Oracle JDK 16已经删除,有些JDK仍存在;

javac HelloWorld.javajaotc —output LibHelloWorld.so —class-name HelloWorld.classjava —XX:AOTLibrary=./LibHelloWorld.so HelloWorld


最后,本文在理解JIT和AOT的思想,它仍在演进和开发中,并且不同JDK发行版实现也不同。 

以上是关于理解Java的JIT和AOT的主要内容,如果未能解决你的问题,请参考以下文章

java 平台的理解

JIT和AOT编译详解

JVM 虚拟机 AOT 和 JIT 即时编译

JVM 虚拟机 AOT 和 JIT 即时编译

ART中AOT和JIT编译器的区别

Dart的特性(JIT 与 AOT、内存分配与垃圾回收、单线程模型)