深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
28017 人已学习
课程目录
已完结 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虚拟机
登录|注册

21 | 方法内联(下)

郑雨迪 2018-09-07
在上一篇中,我举的例子都是静态方法调用,即时编译器可以轻易地确定唯一的目标方法。
然而,对于需要动态绑定的虚方法调用来说,即时编译器则需要先对虚方法调用进行去虚化(devirtualize),即转换为一个或多个直接调用,然后才能进行方法内联。
即时编译器的去虚化方式可分为完全去虚化以及条件去虚化(guarded devirtualization)。
完全去虚化是通过类型推导或者类层次分析(class hierarchy analysis),识别虚方法调用的唯一目标方法,从而将其转换为直接调用的一种优化手段。它的关键在于证明虚方法调用的目标方法是唯一的。
条件去虚化则是将虚方法调用转换为若干个类型测试以及直接调用的一种优化手段。它的关键在于找出需要进行比较的类型。
在介绍具体的去虚化方式之前,我们先来看一段代码。这里我定义了一个抽象类 BinaryOp,其中包含一个抽象方法 apply。BinaryOp 类有两个子类 Add 和 Sub,均实现了 apply 方法。
abstract class BinaryOp {
public abstract int apply(int a, int b);
}
class Add extends BinaryOp {
public int apply(int a, int b) {
return a + b;
}
}
class Sub extends BinaryOp {
public int apply(int a, int b) {
return a - b;
}
}
下面我便用这个例子来逐一讲解这几种去虚化方式。

基于类型推导的完全去虚化

基于类型推导的完全去虚化将通过数据流分析推导出调用者的动态类型,从而确定具体的目标方法。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(12)

  • godtrue
    感觉跟不上了,先过吧!
    已经拉下两节了,日后回头再看看。
    现在仅明白,方法内联-是编译器的一种代码优化手段,会根据不同代码调用方式有不同的优化方式,目的都是为了提高JVM的效率,根本方式,我认为就是采用取巧的方式,提前判断出来可以少做一些事情,然后先提前做一些准备,整体的时间和空间成本会降下来。
    另外,提供小建议,雨迪能否对于这种比较比较抽象的知识,来点生动形象的比喻以便帮助消化,之前在知乎看到一篇关于锁的文章,全篇通过生动形象的比喻讲解锁的本质、分类、各种锁的特点,读起来一下子就明白了。
    2018-09-12
    14
  • 永烁星光
    IR 图分析看了这三篇,好几次,现在还是不甚明白,

    作者回复: 如果都看懂了,可以考虑来我司,或者阿里的JIT专家职位 :)

    一般来说,了解这些优化针对怎样的代码模式,会转化为怎样的代码就可以啦。至于IR图,主要是用来辅助理解具体的优化过程。

    2018-09-10
    7
  • Joker
    漫漫长路,这JAVA一门语言就要如此深究,真特么知无涯
    2019-08-16
    2
  • 李亮亮
    后面两张图是不是还应该有Deopt NullCheckException 这条红色的路径?
    2019-04-11
    2
  • 一少爷
    为什么后面留言的人越来越少了,我觉得后面这些也很关键很有趣呀。对思想的提升很有帮助的。
    2019-02-27
    2
  • hqg
    遇到jvm崩溃,可否帮分析下
    2018-09-07
    1
  • 随心而至
    免费的才是最贵的,享受便利的同时,想搞明白确实不容易,我只有个大的概念。感觉这可以类比CPU里面的冒险与预测来理解,都是基于某种方式来优化,让程序跑的更快些。
    2019-10-25
  • 星星个是大太阳丶
    节点上的P(0)是否是代表方法的参数,C(1)这些代表常量,各个节点的线的颜色是否有什么含义呢?老师能不能指导一下
    2018-09-25
  • Scott
    是每个对象有type profile的限制么?

    作者回复: 每条类型相关字节码,如invokeinterface invokevirtual checkcast instanceof等

    2018-09-10
  • Scott
    是C1在不同的编译层次么?
    2018-09-09
  • Scott
    我也不清楚,什么时候可以有完整的profile,什么时候是不完整的

    作者回复: 回了原提问,这里复制一下:

    每个字节码的type profile有数量限制,比如默认情况下只能存两个不同的动态类型。如果收集profile过程中来了三个不同的动态类型,那么JVM不能全部记下来,因此即时编译器看到的type profile是不完整的。

    2018-09-09
  • Void_seT
    老师,想请教一下,“类型Profile”完整还是不完整,是如何判断的?

    作者回复: 每个字节码的type profile有数量限制,比如默认情况下只能存两个不同的动态类型。如果收集profile过程中来了三个不同的动态类型,那么JVM不能全部记下来,因此即时编译器看到的type profile是不完整的。

    2018-09-08
收起评论
12
返回
顶部