java运行期优化_Java 运行期优化

一、Hotspot虚拟机内的即时编译器解释器与编译器Java 最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”(Hot Spot Code)。为了提高热点代码的效率,在运行时,虚拟机会把这些代码编译成与本地平台相关的机器码,并执行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,JIT)。

解释器与编译器两者各有优势:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译时间,立即执行。程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获得更高的执行效率。当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译执行来提高效率。

同时,解释器可以作为编译器激进优化的一个逃生门,在编译器根据概率选择优化手段,当激进优化不成立的时候,可以通过逆优化退回到解释器状态继续执行。

编译器编译本地代码需要占用程序运行时间,要编译出优化成都更高的代码,所花费的时间可能更长;而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息。

JDK1.7之后,Java默认开启分层策略

第0层:程序解释执行,解释器不开启性能监控功能,可触发第1层编译。

第1层:也称为 C1 编译,将字节码编译为本地代码,进行简单的、可靠的优化,如果有必要加入性能监控的逻辑。

第2层:也称为 C2 编译,将字节码便以为本地代码,但是会启用一些耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

2. 编译对象与触发条件热点代码一般分为两类:1. 被多次调用的方法。2.被多次执行的循环体。第2种虽然编译动作是由循环体所触发的,但是编译器依然会以整个方法作为编译对象。

热点探测的主要方式有两种:

基于采样的热点探测:采用这种方法的虚拟机会周期性的检测各个线程的栈顶,如果发现某个方法经常出现在栈顶,那这个方法就是热点方法。此方法简单高效,而且可以获取方法的调用关系,但是很难精准地确认一个方法的热度,因为容易受到线程阻塞或别的外界因素的影响而扰乱热点探测。

基于计数器的热点探测:虚拟机为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值就认为它是“热点方法”。这种统计方法实现起来麻烦一些,需要为每个方法建立并维护计数器,而且不能直接获取方法的调用关系,但是它的统计结果更为精确严谨。

HotSpot 采用第二种,并为每个方法准备了两类计数器:方法调用计数器(Invocation Counter)和 回边计数器(Back Edge Counter)。方法调用计数器回边计数器方法调用计数器存在半衰周期,过了周期之后,计数就会减半,但是回边计数器并没有。回边计数器稍微复杂一些。

当编译器遇到一条回边指令(回边指令是指控制流向后转的指令),当计数超过阈值时会提交一个OSR编译(栈上替换),并且会减少会变计数器的计数,此外回边计数器计数会溢出,溢出的时候会保持他的溢出状态。

默认情况下,无论是方法调用产生即时编译请求,还是OSR编译请求,虚拟机在编译器还未完成之前,都仍然将按照解释方式继续执行,而编译动作在后台执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值