企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
目前主流的两款商用Java虚拟机(HotSpot、OpenJ9)里,Java程序最初都是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码”(Hot Spot Code),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成本地机器码,并以各种手段尽可能地进行代码优化,运行时完成这个任务的后端编译器被称为即时编译器 ### JIT编译器 即时编译(Just-in-time Compilation,JIT)是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术。在HotSpot实现中有多种选择:C1、C2和C1+C2,分别对应client、server和分层编译。 1. C1编译速度快,优化方式比较保守; 2. C2编译速度慢,优化方式比较激进; 3. C1+C2在开始阶段采用C1编译,当代码运行到一定热度之后采用C2重新编译; 解释器与编译器搭配使用的方式在虚拟机中被称为“混合模式”(Mixed Mode),用户也可以使用参数“-Xint”强制虚拟机运行于“解释模式”(Interpreted Mode),这时候编译器完全不介入工作,全部代码都使用解释方式执行。另外,也可以使用参数“-Xcomp”强制虚拟机运行于“编译模式”(Compiled Mode),这时候将优先采用编译方式执行程序,但是解释器仍然要在编译无法进行的情况下介入执行过程 ### JIT参数配置 TieredCompilation:表示是否开启JVM分层编译(JDK8+默认开启,JDK8以前的版本默认关闭) ``` -XX:+TieredCompilation --开启 -XX:-TieredCompilation --关闭 ``` ### 编译阈值 即时编译JIT只在代码段执行足够次数才会进行优化,在执行过程中不断收集各种数据,作为优化的决策,所以在优化完成之前,例子中的User对象还是在堆上进行分配。 那么一段代码需要执行多少次才会触发JIT优化呢?通常这个值由-XX:CompileThreshold参数进行设置: 1. 使用client编译器时,默认为1500; 2. 使用server编译器时,默认为10000; 意味着如果方法调用次数或循环次数达到这个阈值就会触发标准编译,更改CompileThreshold标志的值,将使编译器提早(或延迟)编译。 除了标准编译,还有一个叫做OSR(On Stack Replacement)栈上替换的编译,如上述例子中的main方法,只执行一次,远远达不到阈值,但是方法体中执行了多次循环,OSR编译就是只编译该循环代码,然后将其替换,下次循环时就执行编译好的代码,不过触发OSR编译也需要一个阈值,可以通过以下公式得到。 ``` -XX:CompileThreshold = 10000 -XX:OnStackReplacePercentage = 140 -XX:InterpreterProfilePercentage = 33 OSR trigger = (CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100 = 10700 ``` 其中trigger即为OSR编译的阈值 参考资料 [https://www.jianshu.com/p/20bd2e9b1f03](https://www.jianshu.com/p/20bd2e9b1f03) http://www.infoq.com/cn/articles/OpenJDK-HotSpot-What-the-JIT