深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
27947 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么我们要学习Java虚拟机?
免费
模块一:Java虚拟机基本原理 (12讲)
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
模块二:高效编译 (12讲)
【工具篇】 常用工具介绍
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
模块三:代码优化 (10讲)
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
模块四:黑科技 (3讲)
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
尾声 (1讲)
尾声 | 道阻且长,努力加餐
深入拆解Java虚拟机
登录|注册

17 | 即时编译(下)

郑雨迪 2018-08-29
今天我们来继续讲解 Java 虚拟机中的即时编译。

Profiling

上篇提到,分层编译中的 0 层、2 层和 3 层都会进行 profiling,收集能够反映程序执行状态的数据。其中,最为基础的便是方法的调用次数以及循环回边的执行次数。它们被用于触发即时编译。
此外,0 层和 3 层还会收集用于 4 层 C2 编译的数据,比如说分支跳转字节码的分支 profile(branch profile),包括跳转次数和不跳转次数,以及非私有实例方法调用指令、强制类型转换 checkcast 指令、类型测试 instanceof 指令,和引用类型的数组存储 aastore 指令的类型 profile(receiver type profile)。
分支 profile 和类型 profile 的收集将给应用程序带来不少的性能开销。据统计,正是因为这部分额外的 profiling,使得 3 层 C1 代码的性能比 2 层 C1 代码的低 30%。
在通常情况下,我们不会在解释执行过程中收集分支 profile 以及类型 profile。只有在方法触发 C1 编译后,Java 虚拟机认为该方法有可能被 C2 编译,方才在该方法的 C1 代码中收集这些 profile。
只要在比较极端的情况下,例如等待 C1 编译的方法数目太多时,Java 虚拟机才会开始在解释执行过程中收集这些 profile。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(10)

  • godtrue
    这节是即时编译器的有关优化、去优化、以及何时优化和为什么去优化的内容。可能比较底层,看不见摸不着,一句两句也说不清楚,所以,有点晦涩。
    不过经过反复看有点感觉了,小结如下:
    1:profile-是收集运行时状态信息,用于编译器优化,当然,收集信息也是耗性能的,所以,也是有前提条件的,当存在优化的可能性时才去费劲吧啦的收集相关信息

    2:本节介绍的两种优化的方式思路,都是采用取巧少做事情的方式实现,是建立在假设有些事情不需要做的前提下采用的优化措施

    3:如果假设失败,那就去优化呗!还用原来的方式老老实实的解释执行就完了

    上述思路是理解了,不过具体实现还是蒙蒙的,应该是水平有限理解不到位吧!整体还是有收获的,所以,非常感谢!

    作者回复: 我觉得总结得很到位了。

    这篇文章主要就是在介绍profile-guided optimization。介绍了两个优化的案例,以及过于乐观的优化出错时怎么补救。

    2018-09-02
    7
  • xiaobang
    想问下生成的机器码如何和其它未编译的字节码交互?比如相互调用,访问对象内的字段,new对象和对应的gc

    作者回复: 在同一方法内,所有的字节码都被编译了。机器码与字节码的切换在方法调用(或者循环回边,对应OSR编译)。

    对于已经在堆上的对象,字节码和机器码所使用对象布局是一致的,解释执行器从哪个偏移量访问某字段,机器码也会从这个偏移量访问字段。(对于标量替换的新建对象,机器码会在去优化时重建对象。)

    JVM里的Runtime是共享的,因此像new对象,实际上都会走到同一个底层方法中。GC是独立的组件,跟字节码机器码没关系,所有new对象都会被JVM runtime追踪。

    2018-10-10
    2
  • 徐志毅
    雨迪老师,请问有什么方式可以跟踪JMM里主内存与工作内存的交互,如什么时候加载到工作内存、什么时候同步到主内存~ 盼回复,谢谢

    作者回复: JMM的工作内存是个虚拟概念,映射到我们的体系架构就是CPU缓存。

    要追踪缓存更新事件的话,估计得看perf,VTune等支持CPU performance counter的工具啦

    2018-08-29
    1
    1
  • jimi
    那么有什么规则,可以让代码尽可能被优化?
    2018-08-29
    1
    1
  • 随心而至
    Windows需要下载对应的dll文件,Google了对应的下载地址
    https://github.com/LiuDui/JavaTools
    2019-10-18
  • 随心而至
    这两节都是讲JVM想做一些假设,来提高程序的运行效率(优化);如果假设错了就重新来过(去优化,退化为解释执行)。
    这里JVM尝试做的事情,感觉和底层CPU想做的分支预测如出一辙。
    具体可参考:https://time.geekbang.org/column/article/102166
    2019-10-18
  • 樱小路依然
    类型profile里,老师的第一个图感觉有点怪怪的,按文字来描述的话,个人理解为:
    - 原来:
        - 测试该类是否与Exception类型一致
        - 测试该类父类是否与Exception类型一致
        - 测试该类祖先类是否与Exception类型一致
        - 测试该类是否有直接实现或者间接实现的接口与Exception类型一致
        - 都不一致,return ((Integer)in).value;

    然后优化为了,直接判断类型是否为 Integer,如果是,则直接返回((Integer)in).value。不经过中间的父类、祖先类、直接间接实现的接口类型判断等
    2019-08-21
  • 乔毅
    请教下老师,JIT利用SIMD进行优化的实现程度?实践中看到大多是仅仅做了循环展开。换言之,有没有什么最佳实践,可以写出JIT SIMD优化友好的代码。

    作者回复: 马上会专门开一篇介绍。可以关注一下OpenJDK的Panama项目,会提供vector API

    2018-09-03
  • 茶底
    大佬我已经把graal拿到手了。目前用了下gu下语言挺好使的。但是这个怎么编译啊。。。

    作者回复: Java 10自带Graal编译器。Oracle OTN下的GraalVM也是编译好的版本,无需另外编译。

    如果想要改Graal源代码后编译,可以参考github.com/oracle/graal/tree/master/compiler/README.md

    2018-08-30
  • 三木子
    感觉好难,我想问下在现实情况下通过编译器调优的情况多吗?

    作者回复: 调优的情况不多的,能做的即时编译器都帮你做了

    2018-08-30
收起评论
10
返回
顶部