jvm中的热点代码检测机制
JVM中的热点代码检测机制主要有三种,分别为基于采样的热点探测,基于计数器的热点探测和基于踪迹的热点探测。
基于采样的热点探测
采用这种方法的虚拟机会周期性地检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,这个方法就是热点方法。
优点:这种方法实现起来较为简单,可以很容易的获取方法调用的关系。
缺点:由于有线程阻塞或别的因素影响,无法精确的对热点进行探测。
基于计数器的热点探测
采用这种方法的虚拟机会为每个方法(甚至是代码块)建立并维护计数器,统计方法的执行次数,执行次数超过一定的阀值就会认为它是热点方法,计数器可以分为两类:
1.方法调用计数器:统计一段时间内方法被调用的次数,如果执行次数超过一定的阈值,就认为他是热点方法。方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数,当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器,那这个方法的调用计数器就会被减少一半,这个过程被称为【方法调用计数器热度的衰减】,而这段时间就称为【方法统计的半衰周期】,进行热度衰减的动作在虚拟机进行垃圾收集时就顺便进行了。
2.回边计数器:主要是统计循环体内的代码执行的次数,在字节码遇到控制流后向后跳转的指令被称为回边,建立回边计数器也是为了触发OSR(On-Stack Replacement,运行时替换栈帧技术)。因为没有计数热度衰减的过程,因此这个计数器统计的就是该方法执行循环的绝对次数,当计数器溢出的时候,它还会把方法计数器的值也调整到溢出的状态,这样下去在再次进入该方法的时候就会执行标准编译过程。比如在空循环的情况下,照样会执行对应的次数,但它是直接跳转到自己,所以JIT编译器去编译这种代码是没有任何意义的。
优点:这种方式更加精确和严谨。
缺点:统计时需要为每个方法建立并维护计数器,而且不能获取方法的调用关系,实现起来较为麻烦。
基于踪迹(Trace)的热点探测
采用这种方式的虚拟机是将一段频繁执行的代码作为一个编译单元,并仅对该代码片段进行编译,该代码片段由一个线性且连续的指令序列组成,仅有一个入口,但有多个出口。也就是说,基于踪迹而编译的热点代码不仅仅局限在一个单独的方法或者代码块中,一条Trace可能对应多个方法,代码中频繁执行的路径就可能被识别成不同的踪迹。
优点:这种方法有着更高的精度,并且能够避免编译不是频繁执行的代码,减少不必要的编译开销。
缺点:这种方法的实现很复杂。
"不知道什么时候开始对你小心翼翼说话了,我记得我从前挺嚣张的。"