一句话解释JVM中的方法内联

166 阅读3分钟

什么是方法内联?

一句话解释就是方法A调用方法B,并不会直接调用方法B而是将方法B的逻辑复制到A中执行。

Java中方法执行原理

Java中调用方法其实就是入栈出栈的过程。

例如Java中存在方法A,现在程序需要执行方法A,那么程序需要转移到方法A的内存地址中执行方法A的逻辑,执行完成之后再返回原来执行的位置。因此就需要保存当前程序执行的位置,以及执行完方法A后的地址。因此就会产生时间和空间的开销。

方法内联是JVM增加的一个优化方案,将需要执行的方法复制到当前方法中执行,避免程序的切换,减少时间和空间复制的开销。

\

    public void methodA() {
        int i = 1;
        i = methodB(i);
    }

    public int methodB(int param) {
        return param + 3;
    }

以上代码中methodA调用methodB,正常调用时线程会执行到methodB的方法栈中,在该方法栈中执行逻辑,执行完成之后再回到methodA的方法栈,整个过程需要记录帧栈的创建以及线程的切换,JVM为了避免这种多层次的调用通过方法内联进行优化。

方法内联优化后,methodA并不会直接调用methodB方法,而是将methodB的逻辑复制到methodA中,相当于两个方法进行合并在一个方法中执行,这样就减少了帧栈的创建和线程的切换等处理。

哪些方法可以进行内联

方法内联是一种优化手段,并不是所有的方法都可以进行内联,也需要一定的条件确定哪些方法可以执行该优化处理。

  • 热点方法:在Java中一些方法会被频繁的调用,当达到一定的调用次数JVM会认为该方法为热点方法。可以通过 - XX:CompileThreshold 参数来调整热点方法阈值。该参数控制的是JVM中即时编译器JIT中编译方法的次数,JIT中存在两种编译器客户端C1和服务端C2,分别对应的热点阈值为1500和10000.(但是不是绝对达到阈值就会进行方法内联,前提是方法体不能过大)。
  • 小方法体:方法内联的前提就是方法体不宜过大,过大的方法体复制到另外方法中也是耗时耗性能的,因此小的方法体更容易执行内联。在JVM中对于热点方法体默认方法体大小小于325字节时会进行方法内联,可以通过 -XX:MaxFreqInlineSize=N 设置该值,非热点代码默认方法体大小小于35字节会进行内联,可以通过 -XX:MaxInlineSize=N 。
  • 特殊修饰符方法体:private、static、final修饰的方法体更容易执行内联,主要考虑是public和protect修饰的方法会需要进行集成或者重写的校验。