JVM深入理解(4)——执行引擎(2)

问题

既然已经内置了JIT编译器,为什么还使用解释器来拖累执行性能呢?

程序启动后,解释器可以马上执行,省去编译时间。即响应速度快。
编译器需要将代码编译为本地代码,需要一定执行时间,但编译完成后,执行效率高。

在此模式下,当Java虚拟器启动时,解释器可以首先发挥作用,而不必等待即时编译器全部编译完成后再执行,这样可以省去许多不必要的编译时间。随着时间的推移,编译器发挥作用,把越来越多的代码编译成本地代码,获得更高的执行效率。

同时,解释执行在编译器进行激进优化不成立的时候,作为编译器的“逃生门”。

如何选择?

热点代码及探测方式
是否启动JIT,需要根据代码被调用执行的频率而定。需要被编译为本地代码的字节码称为热点代码,会被进行深度优化。

多次调用的方法,或在方法体内部循环次数较多的循环体都可以被称为热点代码。由于这种编译方式发生在方法的执行过程中,因此也被称为栈上替换——OSR(On stack Replacement)编译

Hotspot采用的热点探测方式是基于计数器的热点探测。

即为每一个方法都建立两个不同类型的计数器:方法调用计数器回边计数器

  • 前者统计方法的调用次数
  • 后者统计循环体调用次数

方法调用计数器

这个计数器就用于统计方法被调用的次数,它的默认阀值在Client模式下是1500次,在Server模式下是10000次。超过这个阈值,就会触发JIT编译。

阈值可以通过-XX:CompileThreshold来人为设定。

当一个方法被调用时,会先检查该方法是否存在被JIT编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加1,然后判断方法调用计数器回边计数器值之和是否超过方法调用计数器的阀值。如果已超过阈值,那么将会向即时编译器提交一个该方法的代码编译请求。

热度衰减

方法调用计数器并不统计方法被调用的绝对次数,而是一个相对执行频率——一段时间内方法被调用的次数。

当超过时间限度,如果调用次数不足以交给JIT编译器,则调用计数器会减小一半,称为衰减。这段时间称为半衰周期

如果想使用绝对次数,则可以用指令-XX:-UseCouterDecay来关闭热度衰减,如果系统运行时间足够长,绝大部分方法都会被编译成本地代码、

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

回边计数器

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值