晚期(运行期)优化——HotSpot虚拟机内的即时编译器


首先,我们要知道以下概念
热点代码

就是会运行特别频繁的代码,会被编译成机器码。

将热点代码编译成机器码这个任务是由 即时编译器(后台运行期编译器) 完成的。

还有注意一点,即时编译器并不是必须的,但是衡量一款商用虚拟机优秀与否最关键的指标之一。

这一节,我们要完成以下几个问题:

  • 1.何Hotspot虚拟机要使用解释器和编译器并存的架构?
  • 2.为什么Hotspot实现了两个不同的即时编译器(C1、C2)
  • 3.程序什么时候使用解释器执行?什么时候使用编译器执行?
  • 4.哪些代码(热点代码)会被编译成本地代码?如何编译成本地代码?
  • 5.如何从外部观察即时编译器的编译过程和编译结果?

最后,需要注意一点:这一节指的编译器都是Hotspot的即时编译器,虚拟机也指HotSpot虚拟机


一、解释器与编译器

1.1 解释器与编译器的优势

对于问题1,我们就要说一下解释器和编译器各自的优点了。

  • 如果想快速启动和执行,解释器就很不错。但是随着时间的推移,使用编译器会获得更高的执行效率
  • 如果内存资源限制比较大,可以使用解释器节约内存。反之可以使用编译执行类提高执行效率
  • 解释器还可以充当编译器激进优化的逃生门。当激进优化发生问题时,可以通过逆优化退回到解释状态继续执行。

解释器和编译器的交互:

请求即时编译
逆优化
解释器
C1或C2

1.2 C1与C2

C1:Client Compiler
C2:Server Compiler
可以通过“-client”与“-server”参数去强制指定虚拟机运行在Client模式或Server模式。

1.3 混合模式、解释模式、编译模式

混合模式:解释器和编译器混合使用的模式
解释模式:全部代码使用解释方式执行,编译器不介入工作
编译模式:尝试让全部代码在编译方式下运行,实在不行,还是要采用解释方式执行

可以设置“-Xint”或“Xcomp”让编译器运行在解释模式或编译模式。

1.4 分层编译

为了在程序启动响应速度与运行效率之间达到最佳平衡,Hotspot虚拟机会逐渐启用分层编译的策略。对应问题2。

第i层任务
0程序解释执行,不开启性能监控功能,可出发第1层编译
1也称为C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑
2也称C2编译,也将字节码编译为本地代码,但会开启一些编译耗时比较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化

二、编译对象与触发条件

2.1 热点代码

对于问题3,4,什么时候进行解释执行,什么时候进行编译执行?热点代码就编译执行呗!热点代码有两类:

类型编译对象
被多次调用的方法编译对象就是整个方法
被多次执行的循环体编译对象还是整个方法。虽然编译动作是有循环体触发的。这种编译方式是发生在方法执行过程中的,形象的称为栈上替换,即OSR

2.2 热点探测

热点探测,用于判断一段代码是否为热点代码。目前主要的热点探测技术有两种:

种类说明
基于采样的热点探测如果一个方法经常出现在线程的栈顶,那么它就是热点代码。但是,这种方式回受到线程阻塞的影响,进而得到非正常结果
基于计数器的热点探测为每个方法,甚至代码块建立计数器,统计执行次数,当执行次数超过一定阈值就为热点代码。

2.3 HotSpot的基于计数器的热点探测方法

HotSpot为方法提供了两类计数器——方法调用计数器(统计方法调用次数)、回边计数器(统计方法中循环体执行的次数)。下面的计数器触发编译都是C1的,C2要复杂一些。
(1)方法调用计数器出发编译

Java方法入口
是否存在已编译版本
方法调用计数器值加1
两计数器值之和是否超过阈值
向编译器提交编译请求
以解释方式执行方法
Java方法返回
执行编译后的本地代码版本

需要注意的是,当超过一定的时间限度,如果方法的调用次数仍然不超过阈值,那么这个方法的调用计数器就会被减半,这就是方法的——半衰期

(2)回边计数器出发即时编译(疑问:编译对象是方法,而循环体的上一次执行应该保存下来,以便下一次执行时,在机器码中(方法)找到循环体的状态)

遇到回边指令
是否存在已编译版本
执行编译后的本地代码版本
Java方法返回
回边计数器加1
两技术器值之和是否超过阈值
以解释方法继续执行
调整回边计数器值,稍微降低一些,以便解释执行能够继续
//IntExe

注意:”调整回边计数器值,稍微降低一些,以便解释执行能够继续“这一步是要等待编译器输出编译结果的


三、编译过程

C1、C2的编译过程不一样。
(1)C1的编译过程——简单快速的三段式编译器

阶段说明平台相关
第一阶段将字节码转换为高级中间代码平台独立
第二阶段从高级中间代码转换为低级中间代码平台相关
第三阶段使用线性扫描算法优化产生机器代码平台相关

(2)C2的编译过程
C2相对于C1,代码质量提高了,可以减少本地代码的执行时间,从而抵消编译时间。所以也有些非服务端的应用选择使用C2模式的虚拟机运行。

四、查看及分析即时编译结果

后面有时间在写!!!

参考文献

周志明的《深入理解java虚拟机JVM高级特性与最佳实践》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值