深入拆解 Java 虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
87446 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
模块四:黑科技 (3讲)
深入拆解 Java 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

16 | 即时编译(上)

4. 执行C2代码
3. 执行带所有profiling的C1代码
2. 执行仅带profiling的C1代码
1. 执行不带profiling的C1代码
0. 解释执行
编译线程数目
系数s
参数-XX:TierXCompileThreshold
参数-XX:TierXMINInvocationThreshold
参数-XX:TierXInvocationThreshold
参数-XX:CompileThreshold
C2 > C1(1层) > C1(2层) > C1(3层)
参数-server
参数-client
使用参数-XX:+PrintCompilation来打印项目中的即时编译情况
解决单次调用方法包含热循环的性能优化问题
在非方法入口处进行解释执行和编译后代码之间切换
参数-XX:TierXBackEdgeThreshold
参数-XX:CompileThreshold
循环回边计数器
动态调整阈值
阈值
方法的调用次数和循环回边的执行次数
性能比较
5个层次
C2
C1
Graal
C2
C1
实践
Java 8默认采用分层编译
OSR编译的作用
阈值
触发条件
触发条件
Java 7的分层编译
Java 7之前的选择
HotSpot虚拟机
总结与实践
OSR编译
即时编译的触发
分层编译模式
即时编译

该思维导图由 AI 生成,仅供参考

在专栏的第一篇中,我曾经简单地介绍过即时编译。这是一项用来提升应用程序运行效率的技术。通常而言,代码会先被 Java 虚拟机解释执行,之后反复执行的热点代码则会被即时编译成为机器码,直接运行在底层硬件之上。
今天我们便来详细剖析一下 Java 虚拟机中的即时编译。

分层编译模式

HotSpot 虚拟机包含多个即时编译器 C1、C2 和 Graal。
其中,Graal 是一个实验性质的即时编译器,可以通过参数 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler 启用,并且替换 C2。
在 Java 7 以前,我们需要根据程序的特性选择对应的即时编译器。对于执行时间较短的,或者对启动性能有要求的程序,我们采用编译效率较快的 C1,对应参数 -client。
对于执行时间较长的,或者对峰值性能有要求的程序,我们采用生成代码执行效率较快的 C2,对应参数 -server。
Java 7 引入了分层编译(对应参数 -XX:+TieredCompilation)的概念,综合了 C1 的启动性能优势和 C2 的峰值性能优势。
分层编译将 Java 虚拟机的执行状态分为了五个层次。为了方便阐述,我用“C1 代码”来指代由 C1 生成的机器码,“C2 代码”来指代由 C2 生成的机器码。五个层级分别是:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java虚拟机即时编译技术是本文的重点,详细介绍了HotSpot虚拟机中的分层编译模式,包括C1、C2和Graal等即时编译器。文章讲解了分层编译的五个执行状态,不同层级的性能特点,以及即时编译的触发条件。此外,还介绍了启用分层编译时的动态调整阈值系统和编译线程分配规则。另外,OSR编译和实践环节也得到了详细解释。总的来说,本文内容涵盖了即时编译的原理、触发条件和优化策略,对于想深入了解Java虚拟机即时编译技术的读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(29)

  • 最新
  • 精选
  • 有点费解,不过还好又明白了一些东西,小结如下: 1:即时编译-直接将Java字节码编译成机器码,运行在底层硬件之上,这么玩是为了提高代码的执行效率,通俗点就是能使代码跑的更快一些 2:即时编译的触发点是热点代码,即 即时编译仅针对热点代码来触发,热点代码是通过方法的调用次数或者回边循环的次数来标示的,这里也侧面反映出来即时编译是针对方法块的,有个疑问❓为什么不把所有代码都即时编译一下呢?这样程序的执行效率不是更快吗?为什么还分热点非热点呢? 3:分层编译的设计也有点奇怪,为什么要这样呢?使用最快的编译代码编译器编译的代码不是更好吗? 4:解释执行-将Java字节码一段一段的编译成机器码在底层硬件上运行,即时编译是一个相对解释执行而言的概念,它将热点代码先编译成机器码缓存起来,在解释执行字节码的时候判断出已经缓存起来了就不在编译直接获取执行就可以了

    作者回复: 2. 即时编译是以方法为单位的。动态编译比较耗时,如果花了大量CPU资源编译出来的机器码运行不了几次,就很浪费了。 3. 机器码越快,需要的编译时间就越长。分层编译是一种折衷的方式,既能够满足部分不那么热的代码能够在短时间内编译完成,也能满足很热的代码能够拥有最好的优化。

    2018-08-28
    51
  • 槛外人
    为什么一块代码会被2层编译后还会被3、4层编译?不能某一层编译就完了吗?

    作者回复: 其中一个原因是快速地收集profile,所以会用2 3层编译后的代码,既能够高效运行,也能够收集最终用来4层编译的profile

    2018-11-06
    8
  • 泰格杨
    去优化是啥意思?

    作者回复: 就是从执行机器码切换回解释执行,下一篇会详细介绍。

    2018-08-27
    7
  • 杨春鹏
    Java中的即时编译器,是不是重新将java代码编译成机器码,并没有使用class文件?

    作者回复: 确切地说,即时编译器将加载进VM中的类的某个方法所对应的byte数组编译为机器码。你也可以理解为从class文件到机器码。

    2018-08-28
    5
  • 郑杰
    能说下及时编译的结果是什么样的吗,然后他是怎么跟解释执行一起运行的

    作者回复: 编译结果就是二进制码,下一篇有具体示例。解释执行遇到方法调用时,JVM会判断目标方法是否被编译。如果是,就跳转至编译好的二进制码中。

    2018-08-27
    5
  • Leon Wong
    有个小问题,1、4层是终止(接受)状态的前提是,您的五层应该从0开始,到4层结束,但是您现在1层开始,5层结束,那么终止状态应该是2层和5层。

    作者回复: 对的,我原稿里是从0开始,可能MD语法给识别错了。

    2018-09-17
    4
    3
  • 大场镇车王
    请问带所有profiling是什么意思 所有是个什么概念

    作者回复: 下篇会讲。主要有分支跳转指令的branch profile,和类型相关指令的type profile。

    2018-08-27
    3
  • 公号-技术夜未眠
    请问即时编译的对象是方法级还是语句块级?

    作者回复: 一般都是方法级。 OSR编译会拿热循环作为编译对象。

    2018-08-27
    3
  • Geek_987169
    老师,问下,中止状态是什么意思?

    作者回复: 这里的上下文是在讲编译层次吧?指的是到了1层或者4层之后,就不再就同一个方法触发新的编译请求,除非是OSR编译或者已被去优化

    2018-10-20
    1
  • 魏春河
    我记得前面提到过CompileThreshold 默认是15,今天怎么成1500了?

    作者回复: 15应该是反射调用从本地实现切换为动态实现吧。这里的1500是即时编译的。

    2018-08-28
    1
收起评论
显示
设置
留言
29
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部