【深入理解Java 虚拟机之 即时编译器】1122 编译对象与触发条件

1、热点代码

A: 被多次调用的方法,被多次执行的循环体。

2、栈上替换

方法的栈帧还在栈上,方法就被替换了 => 针对循环体热点代码

3、“热点探测”(Hot Spot Code Detection)

知道某段代码是不是热点代码,是不是需要触发即时编译,这个行为。

A: 基于采样的热点探测(Sample Based Hot Spot Code Detection) => 很难精确地确认一个方法的热度(受外间因素影响)

虚拟机会周期性地检查各个线程的调用栈顶,如果发现某个(或某些)方法经常出现在栈顶,那这个方法就是“热点方法”。

B: 基于计数器的热点探测(Counter Based Hot Spot Code Detection)。 => 统计结果严谨

虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值就认为它是“热点方法”

4、J9用第一种采样热点探测,HotSpot虚拟机中使用第二种基于计数器的热点探测方法

5、HotSpot的两类计数器:

A: 方法调用计数器(InvocationCounter)和回边计数器(Back Edge Counter,“回边”的意思就是指在循环边界往回跳转。

B: 方法调用计数器(基于方法被调用的次数):它的默认阈值在客户端模式下是1500次,在服务端模式下是10000次。

在这里插入图片描述

阈值可以通过虚拟机参数-XX:CompileThreshold来人为设定

C: 回边计数器(在字节码中遇到控制流向后跳转的指令就称为“回边(Back Edge))统计一个方法中循环体代码执行的次数,触发栈上的替换编译。

在这里插入图片描述

设置参数-XX:OnStackReplacePercentage来间接调整回边计数器的阈值

虚拟机运行在客户端模式下,回边计数器阈值计算公式为:方法调用计数器阈值(-XX:CompileThreshold)乘以OSR比率(-XX:OnStackReplacePercentage)除以100。

其中-XX:OnStackReplacePercentage默认值为933,如果都取默认值,那客户端模式虚拟机的回边计数器的阈值为13995。

虚拟机运行在服务端模式下,回边计数器阈值的计算公式为:方法调用计数器阈值(-XX:CompileThreshold)乘以(OSR比率(-XX:OnStackReplacePercentage)减去解释器监控比率(-XX:InterpreterProfilePercentage)的差值)除以100。

其中-XX:OnStackReplacePercentage默认值为140,-XX:InterpreterProfilePercentage默认值为33,如果都取默认值,那服务端模式虚拟机回边计数器的阈值为10700。

6、半衰周期(Counter Half Life Time)(方法计数器有半衰期)

一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那该方法的调用计数器就会被减少一半,这个过程被称为方法调用计数器热度的衰减(Counter Decay)

使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数。

使用-XX:CounterHalfLifeTime参数设置半衰周期的时间,单位是秒。

注意: 触发编译不是立即替换!是等代码编译好!执行才会替换方法的执行地址。

猜你喜欢

转载自blog.csdn.net/qq_40996741/article/details/109090021