HotSpot编译器与即时编译

        大部分主流商用虚拟机中都包含解释器与编译器,解释器与编译器用处不同,当程序需要迅速启动和执行时,解释器先发挥作用,省去编译时间,立即执行。在程序运行后,随着时间推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。

        在java8中默认使用解释器与编译器搭配的混合模式(mixed mode),如果想只使用解释器可以通过设置-Xint强制虚拟机运行于解释模式(interpreted iode),此时编译器不介入工作。如果想只使用编译器可以通过设置-Xcomp强制虚拟机运行于编译模式(compiled mode),可通过java -version显示这三种模式。

混合模式
java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

解释模式
java -Xint -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, interpreted mode)

编译模式
java -Xcomp -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, compiled mode)

HotSpot编译器

        HotSpot内置了两个即时编译器Client Complier(C1)和Server Complier(C2),其编译过程不同。

        C1编译器是一个简单快速的编译器,主要的关注点在于局部性的优化,适用于执行时间较短或对启动性能有要求的程序。

        C2 编译器是为长期运行的服务器端应用程序做性能调优的编译器,适用于执行时间较长或对峰值性能有要求的程序。

        在java7以前需要根据程序特性选择不同编译器。java7引入了分层编译,可以通过参数 -client或-server强制指定虚拟机的编译模式,分层编译将jvm虚拟机状态分为5层。

        第 0 层:程序解释执行,默认开启性能监控功能(profiling),如果不开启,可触发第2层编译。

        第 1 层:将字节码编译为本地代码,进行简单可靠的优化,不开启 profiling的C1编译。

        第 2 层:开启 profiling,仅执行带方法调用次数和循环回边执行次数 profiling的 C1 编译。

        第 3 层:执行所有带 profiling的 C1 编译。

        第 4 层:执行C2编译。

        通常情况下C2编译效率高于C1,C1编译中由于使用Profiling其效率为第1层>第2层>第3层。在java8对分层编译做了进一步优化,默认开启分层编译,如果只想使用C1编译可以在开启分层编译的同时设置参数-XX:TieredStopAtLevel=1。如果想只使用C2编译可以通过-XX:-TieredCompilation关闭分层编译。

即时编译

        即时编译依赖于编译器执行,与解释器执行流程不同,当虚拟机发现某个方法或代码块的运行特别频繁的时候,就会把这些代码认定为热点代码,为了提高热点代码的执行效率,在运行时,即时编译器会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化,然后保存到内存中。

        jvm根据方法调用计数器(Invocation Counter)以及回边计数器(Back Edge Counter)来触发即时编译。触发条件为方法计数器和回边计数器之和超过 -XX:CompileThreshold 指定的阈值时,则会触发即时编译。在分层编译中会通过profiling统计这两项指标。

        方法调用计数器:用于统计方法被调用的次数,通过-XX: CompileThreshold 指定阈值,默认阈值在 C1编译器中为1500 次,在 C2 编译中中为10000 次,启用分层编译后,-XX: CompileThreshold 指定的阈值将失效。此时将会根据当前待编译的方法数以及编译线程数动态计算。

        回边计数器:用于统计一个方法中循环尾到循环头的次数,通过-XX: OnStackReplacePercentage指定阈值,默认阈值在C1编译器中为为 13995次,C2编译器中为为 10700次。启用分层编译后,-XX: OnStackReplacePercentage 指定的阈值将失效。通用会根据当前待编译的方法数以及编译线程数动态计算。

OSR编译

        OSR(On-Stack-Replacement)编译指在程序执行过程中,动态地替换掉 Java 方法栈桢,从而使得程序能够在非方法入口处进行解释执行和编译后的代码之间的切换。OSR是一种以循环为单位的即时编译通过回边计数器触发。其阈值为-XX:CompileThreshold的倍数,默认阈值在C1编译器中为13500,C2编译器中为10700。

        

        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值