深入理解JVM后端优化技术-方法内联

       相关系列

深入理解JVM后端优化技术-逃逸分析(Escape Analysis)-CSDN博客

深入理解JVM后端优化技术-锁消除(Lock Elision)-CSDN博客

深入理解JVM后端优化技术-锁粗化(Lock Coarsening)-CSDN博客

 jvm只是负责依次将字节码指令逐次转换成机器码。而在转换过程中,JVM会对做一些代码优化,不管怎么样,就算程序员写出了很烂的代码,JVM也能保持一个不错的执行效率。这就是编绎优化

方法内联定义

        方法内联就是把被调用方的方法代码复制到调用方的方法中,避免真实的方法调用。这样可以频繁的减少创建栈帧。

示例1

代码

下面是示例代码:

package com.dzend.mall.order;

public class InLineDemo {

    private int add(int x1,int x2,int x3,int x4){
        return add2(x1,x2) + add2(x3,x4);
    }
    //内联优化
    private int add2(int x1,int x2){
        return x1+x2;
    }

    public static void main(String[] args) {
        InLineDemo inLineDemo = new InLineDemo();
        //超过⽅法调⽤计数器的阈值 100000 次,才会进⼊ JIT 实时编译,进⾏内联优化。
        for(int i=0;i<100000;i++) {
            inLineDemo.add(1, 2, 3, 4);
        }
    }
    
}

jvm参数设置

设置JVM参数:

-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions

执行过后可以看到

这个成为热点代码必须要达到JVM设置的阈值。当没有达到设置的阈值时,就不会看到方法内联了。

  方法内联除了把目标方法的代码“复制”到发起调用的方法中,避免了真实的方法调用。然而,JVM方法内联过程没有这么简单。而且,方法内联还有更多的后续优化手段。

示例二

代码

看下面代码:

package com.dzend.mall.order;

public class InLineDemo {

    private static void one(Object obj){
        if(obj !=null){
            System.out.printf("do something");
        }
    }
    //内联优化,会把无用代码消除
    private static void two(){
       Object obj = null;
       one(obj);
    }

    public static void main(String[] args) {
        Long startTime = System.currentTimeMillis();
        
        for(int i=0;i<1000000;i++) {
            two();
        }
        System.out.println(">>>>>>>>"+(System.currentTimeMillis()-l));
    }

}

代码分析

one和two是独立的二个方法,但是将one方法内联到two方法后,就可以把这个无用的死代码"Dead Code“。然后,JVM虚假机就可以进行dead code elimination死代码抹除的优化。

JDK8中JVM关于方法内联的参数

-XX:+Inline 启用方法内联。默认开启。

-XX:InlineSallCode=size 用来判断是否需要对方进行内联优化。如果一个方法编绎后的字节码大小于这个值,就无进行内联。默认值是1000bytes。

-XX:MaxInlineSize=size 设定内联方法的最大字节数。如果一个方法编绎后的字节码大于这个值,则无法进行内联。默认值是325bytes。

-XX:FreqInlieSize=size 设定热点方法进行内联的最大字节数。如果一个热点方法编绎后的字节大于这个值,则无法进行内联。默认值为325bytes

-XX:MaxTrivialSize=size 设定要进行内联的琐碎方法的最大字节数(Trivial Method:通常指那些只包含一两行语句,并且逻辑非常简单的方法。默认为6bytes.

-XX:+PrintInlining 打印内联决策,通过这个指令可以看到哪些方法进行了内联。默认是关闭的。另外,这个参数要配合-XX:+UnlockDiagnosticVMPOptions参数使用。

方法内联与编写代码技巧

比上面的相关参数不难分析出,编写代码的时候可以通过一些方法提升方法内联发生的概率。

1、在编程中,尽量多写小方法,避免写大方法。方法太大不光会导致方法无法内联。加外,成为热点代码后,还会占用更多的CodeCache。

2、在内存不紧张的情况下,可以通过调整JVM参数,减少热点阈值或增加方法体阈值,让更多的方法进行内联。

3、尽量使用final,private,static关键字修饰方法。该当如果需要继承(使用Invokevirtual指令调用) ,那具体调用 的方法,就只能在运行到这一行代码时才能确定,编绎器很难在编绎时得出绝对正确的结论,也就加大了编译执行的难度。

相关推荐

  1. 深入理解JVM优化技术-锁消除(Lock Elision)

    2024-04-11 19:52:03       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-11 19:52:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-11 19:52:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-11 19:52:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-11 19:52:03       18 阅读

热门阅读

  1. 【QT教程】QT6 Web开发入门

    2024-04-11 19:52:03       15 阅读
  2. ubuntu22.04 静态IP设置脚本

    2024-04-11 19:52:03       15 阅读
  3. set和map

    set和map

    2024-04-11 19:52:03      12 阅读
  4. FP独立站收款必备!AB站跳转轮询全解析

    2024-04-11 19:52:03       13 阅读
  5. 创业之路:从市场洞察到产品实现的全方位指南

    2024-04-11 19:52:03       11 阅读
  6. Spring Boot 经典面试题(四)

    2024-04-11 19:52:03       13 阅读
  7. Vue链接跳转地址 href 中有参数带有#

    2024-04-11 19:52:03       13 阅读