HotSpot JIT内联策略:自上而下或下至上

时间:2013-09-11 09:43:19

标签: java inline jit jvm-hotspot

假设我们有3个方法:从方法1调用方法2,从方法2调用方法3。 方法2和3各自的大小为30字节码。另外,假设确定性方法2总是从方法1中调用一次,方法3总是从方法2中调用一次。

如果方法2首先被内联,则方法3将直接从方法1的主体调用,并且可以依次内联。如果方法3首先内联到方法2中,后者的大小将变为大约60个字节码,并且无法内联,因为默认MaxInlineSize阈值是35个字节码。

HotSpot JIT以哪种顺序内联方法:自上而下或下至上?

2 个答案:

答案 0 :(得分:19)

MaxInlineSize影响至少执行一次但少于MinInliningThreshold次的方法的编译。对于执行超过MinInliningThreshold的方法,有一个不同的设置-XX:FreqInlineSize=…具有更大(平台相关)的默认值。无论MaxInlineSize如何,热点仍然是内联的。您可以通过运行-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:MaxInlineSize=0的应用程序来测试它。它仍将报告热点的内联(这些与评论“(热)”)。只有先前报告的方法与评论“已执行< MinInliningThreshold时间“可能会使评论”太大“。如果您设置FreqInlineSize,您可能会收到“hot method too big”之类的评论。我从未使用默认设置看到它们。

答案 1 :(得分:3)

使用参数运行以下代码显示两个方法m3首先内联。 我为jvm使用了以下参数:-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining。首先,内联首先执行计数达到内联阈值的方法。在我们的情况下m3。因此,用于测试的热点是首先执行m3并且m2执行结束。

使用jdk7_u40运行代码,禁用TieredCompilation,Windows 8上的服务器模式框。 该命令的输出是:

            @ 66   java.lang.String::indexOfSupplementary (71 bytes)   too big
            @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 11   methodTest::m2 (35 bytes)   inline (hot)
              @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 14   methodTest::m1 (25 bytes)   inline (hot)
              @ 11   methodTest::m2 (35 bytes)   inline (hot)
                @ 21   methodTest::m3 (31 bytes)   inline (hot)

m1的尺寸为25 bytesm235 bytesm331 bytes

public class methodTest {

    public static void main(String[] args) {
        doTest();
    }

    int i = 0;
    int j = 0;
    int k = 0;

    private static void doTest() {
        methodTest m = new methodTest();

        for (int i = 0; i < 1000000000; i++) {
            m.m1();
        }
        System.out.println(m.i);
        System.out.println(m.j);
        System.out.println(m.k);
    }

    private void m1() {
        i++;
        m2();
        j++;
    }

    private void m2() {
        i++;
        i++;
        m3();
        j++;
    }

    private void m3() {
        i++;
        j++;
        k++;
    }
}