深入拆解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虚拟机
登录|注册

20 | 方法内联(上)

郑雨迪 2018-09-05
在前面的篇章中,我多次提到了方法内联这项技术。它指的是:在编译过程中遇到方法调用时,将目标方法的方法体纳入编译范围之中,并取代原方法调用的优化手段。
方法内联不仅可以消除调用本身带来的性能开销,还可以进一步触发更多的优化。因此,它可以算是编译优化里最为重要的一环。
以 getter/setter 为例,如果没有方法内联,在调用 getter/setter 时,程序需要保存当前方法的执行位置,创建并压入用于 getter/setter 的栈帧、访问字段、弹出栈帧,最后再恢复当前方法的执行。而当内联了对 getter/setter 的方法调用后,上述操作仅剩字段访问。
在 C2 中,方法内联是在解析字节码的过程中完成的。每当碰到方法调用字节码时,C2 将决定是否需要内联该方法调用。如果需要内联,则开始解析目标方法的字节码。
复习一下:即时编译器首先解析字节码,并生成 IR 图,然后在该 IR 图上进行优化。优化是由一个个独立的优化阶段(optimization phase)串联起来的。每个优化阶段都会对 IR 图进行转换。最后即时编译器根据 IR 图的节点以及调度顺序生成机器码。
同 C2 一样,Graal 也会在解析字节码的过程中进行方法调用的内联。此外,Graal 还拥有一个独立的优化阶段,来寻找指代方法调用的 IR 节点,并将之替换为目标方法的 IR 图。这个过程相对来说比较形象一些,因此,今天我就利用它来给你讲解一下方法内联。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(12)

  • 木心
    IR只有我看不懂吗?各颜色的模块代表什么意思,还有不同钥匙的线代表什么意思?
    2018-09-11
    29
  • godtrue
    方法内联,一种优化代码的手段,其目的就是想让代码执行的更快一些,它怎么做到的呢?以前记录过性能优化的思路就那么几种,让赶的快的干,如果实现不了就让干的快的多干,干的慢点少干。方法内联是采用少干活的方式来提高效率的,直接将对应方法的字节码内联过来,省下了记录切换上下文环境的时间和空间。
    2018-09-10
    2
  • 刘冠利
    请问final的使用对内联有多大帮助?

    作者回复: 在(下)篇有介绍

    2018-09-06
    2
  • 随心而至
    IR的图我也没看懂,不过内联想要做的事情看明白了,感觉和C/C++里面的define有点像
    2019-10-25
    1
  • gogo
    老师,是只有即时编译才会进行方法内联吗?jdk编译java源码的时候会进行方法内联吗
    2019-09-30
    1
  • 乘风
    感谢雨迪,之前对方法内联疑惑很多,知道有方法内联这件非常优秀的优化技术,却不知道如何在一定范围内优化代码来提高方法内联的几率。


    2019-07-18
  • 金龟
    默认的内联时机是什么样的呢?比如默认在什么情况方法会内联
    2019-01-28
  • Geek_987169
    老师,能否提供一个学习IR图的地址?

    作者回复: 这方面的知识网上并不多。可以知乎上搜Sea of nodes IR,看R大的回答,有不少链接可以参考。

    2018-10-21
  • Leon Wong
    建议老师单独开个专题讲IGV生成的IR图
    2018-09-27
  • 三木子
    请问方法内联是发生在解释执行阶段吗?这里方法调用可以理解为解释执行中的小部分解释吗?有些困惑,麻烦老师解释执行下。

    作者回复: 方法内联只发生在即时编译器中。

    方法调用就是字面意思。在即时编译过程中,即时编译器会将当前方法所包含的方法调用的目标方法纳入编译范围中。

    2018-09-07
  • Scott
    最后引入常量后foo方法两个图是一样的,后面一幅图应该if节点被优化掉了吧,直接返回0了。

    作者回复: 多谢指出!

    2018-09-05
  • 皮卡皮卡丘
    这个是方法内联信息吗,怎么和代码里的信息有差别?@ 1 java.lang.Object::<init> (1 bytes)
                                  @ 5 java.lang.AbstractStringBuilder::appendNull (56 bytes) callee is too large
                                  @ 10 java.lang.String::length (6 bytes)
                                  @ 21 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
                                    @ 17 java.lang.AbstractStringBuilder::newCapacity (39 bytes) callee is too large
                                    @ 20 java.util.Arrays::copyOf (19 bytes)
                                      @ 11 java.lang.Math::min (11 bytes)
                                      @ 14 java.lang.System::arraycopy (0 bytes) intrinsic
                                  @ 35 java.lang.String::getChars (62 bytes) callee is too large
                                  @ 1 java.lang.Object::<init> (1 bytes)
                                  @ 13 java/lang/StringIndexOutOfBoundsException::<init> (not loaded) not inlineable
                                  @ 30 java/lang/StringIndexOutOfBoundsException::<init> (not loaded) not inlineable
                                  @ 65 java/lang/StringIndexOutOfBoundsException::<init> (not loaded) not inlineable
                                  @ 75 java.util.Arrays::copyOfRange (63 bytes) callee is too large
                                  @ 17 java.lang.AbstractStringBuilder::newCapacity (39 bytes) callee is too large
                                  @ 20 java.util.Arrays::copyOf (19 bytes)
                                    @ 11 java.lang.Math::min (11 bytes)
                                    @ 14 java.lang.System::arraycopy (0 bytes) intrinsic
                                  @ 66 java.lang.String::indexOfSupplementary (71 bytes) callee is too large
                                  @ 3 java.lang.String::indexOf (70 bytes) callee is too large
                                  @ 1 java.lang.Character::toUpperCase (9 bytes)
                             
                     

    作者回复: PrintInlining将打印JVM里所有即时编译的内联优化信息,所以看起来比较杂

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