【13】即时编译(JIT)

概念

即时编译是用来提升应用运行效率的技术。代码会先在JVM上解释执行,之后反复执行的热点代码会被即时翻译成为机器码,直接运行在底层硬件上。

分层编译模式

  • HotSpot包含多个即时编译器:C1、C2和Graal(Java 10,实验性)

  • 在Java 7之前,需要根据程序的特性选择对应的即时编译器

    • 对于执行时间较短或对启动性能有要求的程序,采用编译效率较快的C1,对应参数:-client
    • 对于执行时间较长或对峰值性能有要求的程序,采用生成代码执行效率较快的C2,对应参数:-server
  • Java 7引入了分层编译(-XX:+TieredCompilation),综合了C1的启动性能优势和C2的峰值性能优势

  • 分层编译将JVM的执行状态分了5个层次

    • 0:解释执行(也会profiling)
    • 1:执行不带profiling的C1代码
    • 2:执行仅带方法调用次数和循环回边执行次数profiling的C1代码
    • 3:执行带所有profiling的C1代码
    • 4:执行C2代码

C1代码指C1生成的机器码;C2代码指C2生成的机器码
对于C1代码三种执行状态 1层>2层>3层(profiling越多,执行的效率越低)
C2代码的执行效率高于C1 大约30%

  • profiling:在程序执行过程中,收集能够反映程序执行状态的 数据(所收集的数据被叫做profile)。

编译路径

  • 对于分层编译的5个层次的执行状态中,1层和4层为终止状态。(当一个方法被终止状态编译后,如果编译后的代码没有失效,那么JVM不会再次发出该方法的编译请求)

在这里插入图片描述

  • common:通常情况下,热点方法会被3层的C1编译,然后再被4层的C2编译
  • trivaial method: 如果方法的字节码数目较少(如getter/setter),并且3层的profiling没有可收集的数据,JVM会在3层的C1编译后,直接选用1层的C1编译
  • c1 busy: 在C1忙碌的情况下,JVM在解释执行过程中对程序进行profiling,而后直接由4层的C2编译
  • c2 busy: 在C2忙碌的情况下,方法会被2层的C1编译,然后再被3层的C1编译,以减少方法在3层的执行时间

JIT的触发

  • JVM是依据方法的调用次数以及循环回边的执行次数来触发JIT的

  • 在不启动分层编译时
    当方法的调用次数和循环回边的次数的和超过-XX:CompileThreshold,便会触发JIT(使用C1时,该值为1500,使用C2时,该值为10000)

  • 在启动分层编译时
    阈值大小是动态调整的。

  • 决定一个方式是否是热点代码的因素,及时编译器是根据以下这两个计数器的和来触发的

    • 方法的调用次数
    • 循环回边的执行次数

优化

当方法被 3 层 C1 所编译时,生成的 C1 代码将收集条件跳转指令的分支 profile,以及类型相关指令的类型 profile。在部分极端情况下,Java 虚拟机也会在解释执行过程中收集这些 profile。

基于分支 profile 的优化以及基于类型 profile 的优化都将对程序今后的执行作出假设。这些假设将精简所要编译的代码的控制流以及数据流。在假设失败的情况下,Java 虚拟机将采取去优化,退回至解释执行并重新收集相关的 profile。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值