标签:jit编译器
作者:郭嘉
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWell
为什么会Java虚拟机会同时存在解释器和编译器呢?
这是为了兼顾启动效率和执行效率两个方面。Java程序最初是通过解释器进行解释执行的,当虚拟机返现某个方法或代码块的运行特别频繁时,就会把这段代码标记为热点代码,为了提供热点代码的执行效率,在运行时,虚拟机就会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化。
当编译器做的激进优化不成立,不如加载了新类后类型继承结构出现变化,出现了罕见陷阱时可以进行逆优化退回到解释状态继续执行。
以上描述的两种配合关系如下图所示:
HotSpot JVM内置了两个编译器,分别是Client Complier和Server Complier,虚拟机默认是Client模式,我们也可以通过
而无论是Client模式还是Server模式,虚拟机都会运行在解释器和编译器配合使用的混合模式下,可以通过
以上描述的运行模式如下图所示:
为什么会存在分层编译?
这是因为编译器编译本机代码需要占用程序运行时间,要编译出优化程度更高的代码锁花费的时间可能更长,而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息,这对解释执行的速度也有影响。为了在程序启动响应速度和运行效率之间寻找平衡点,因此采用分层编译的策略。
分层策略如下所示:
编译对象即为会被编译优化的热点代码,有以下两类:
上面描述中使用多次这个概念,那么什么算多次呢?
这就牵扯到触发条件这个概念,判断一段代码是否是热点代码,是否需要触发即时编译,这种行为成为热点探测(Spot Dectection)。
热点探测有两种手段:
虚拟机会周期性的检查各个线程的栈顶,如果发现某些方法经常性的出现在栈顶,那么这个方法就是热点方法。
虚拟机会为每个方法或代码块建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值就认为他是热点方法。
HotSpot JVM使用第二种方法基于计数器的热点探测方法,它为每个方法准备了两类计数器:
这个阈值在Client模式下是1500次,在Server模式下是10000此,这个阈值可以通过参数-XX:CompileThreadhold来人为设定。
如果不做任何设置,方法调用次数统计的并不是方法被调用的绝对次数,而是相对的执行频率,即一段时间内方法被调用的次数,当超过一定时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器会被减少一半,这个过程被称为方法调用计数器的热度衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(Counter Half Life Time)。同样也可以使用参数-XX:-UseCounterDecay来关闭热度衰减。
方法调用计数器触发即时编译的整个流程如下图所示:
什么是回边?
在字节码遇到控制流向后跳转的指令称为回边(Back Edge)。
回边计数器是用来统计一个方法中循环体代码执行的次数,回边计数器的阈值可以通过参数-XX:OnStackReplacePercentage来调整。
方法调用计数器闭值( CompileThreshold) xOSR比率(OnStackReplacePercentage) / 100
其中OnSlackReplacePercentage默认值为933,如果都取默认值.那Client模式虚拟机的回边计数器的阂值为13995.
方法调用计数器阂值(CompileThmshold) x (OSR比率(OnStackReplacePercentage) - 解释器监控比率(InterpreterProffePercentage) / 100
其中OnStackReplacePementage默认值为140. InterpreterPmfilePercenmgc默认值为33.
如果都取默认值,BF Server模式虚拟机回边计数器的阑值为10700。
回边计数器触发即时编译的流程如下图所示:
回边计数器与方法调用计数器不同的是,回边计数器没有热度衰减,因此这个计数器统计的就是循环执行的绝对次数。
在默认设置下,无论是方法调用产生的即时编译请求,还是OSR编译请求,虚拟机在代码编译器还未完成之前,都仍然按照解释方式继续进行,而编译动作则在后台的编译线程中继续进行。也可以使用-XX:-BackgroundCompilation来禁止后台编译,则此时一旦遇到JIT编译,执行线程向虚拟机提交请求后会一直等待,直到编译完成后再开始执行编译器输出的本地代码。
那么在后台编译过程中,编译器做了什么事呢?
Server Compiler和Client Compiler的后台编译过程是不一样的,我们来分别看一下。
整个过程如下图所示:
Server Compiler是专门面向服务端的典型应用并为服务器的性能配置特别调整过的编译器,它会执行所有经典的优化动作,如下所示:
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:jit编译器
原文地址:http://blog.csdn.net/allenwells/article/details/46802791