理解Java的JIT和AOT
Posted 整码阁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解Java的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.java
jaotc —output LibHelloWorld.so —class-name HelloWorld.class
java —XX:AOTLibrary=./LibHelloWorld.so HelloWorld
最后,本文在理解JIT和AOT的思想,它仍在演进和开发中,并且不同JDK发行版实现也不同。
以上是关于理解Java的JIT和AOT的主要内容,如果未能解决你的问题,请参考以下文章