逃避分析存疑

时间:2015-10-18 20:41:29

标签: java jvm escape-analysis

我以为我会做一些逃避分析的实验(Java 8,64位服务器JVM)。我提出了这个非常愚蠢的应用程序",我创建了很多地址对象(它们包含邮政编码,街道,国家和生成对象的时间戳。此外,地址有一个isOk( )方法,如果时间戳可以用7 ...整除,则返回true。

所以这是程序:

private boolean generate() {
    boolean valid = true;
    for (int i=0;i<1_000_000_000;i++) {
        valid = valid && doGenerate();
    }

    return valid;
}

private boolean doGenerate() {
    long timeGenerated = System.currentTimeMillis();
    Address address = new Address(1021, "A Street", "A country", timeGenerated);
    return address.isOk();
}

到目前为止,我用jVisualVM对其进行了分析,当它运行时,堆上没有Address对象。整个应用程序在几秒钟内完成。

然而,当我像这样重构它时:

private boolean generate() {
    boolean valid = true;
    for (int i=0;i<1_000_000_000;i++) {
        long timeGenerated = System.currentTimeMillis();
        Address address = new Address(1021, "A Street", "A country", timeGenerated);
        valid = valid && address.isOk();
    }

    return valid;
}

Baaang,没有逃避分析,每个Address对象最终都在堆上分配了大量的垃圾收集周期。为什么会这样?我的意思是,Address实例不会以任何方式转义(在第二个版本中,Address对象&#39;范围甚至更窄,它们不会逃避该方法,甚至不是for循环块),为什么这两个版本表现得如此不同?

1 个答案:

答案 0 :(得分:4)

你写“如果时间戳可用7 整除则返回true”。这应该是显而易见的,会发生什么。在您的第一个代码中:

boolean valid = true;
for (int i=0;i<1_000_000_000;i++) {
    valid = valid && doGenerate();
}
return valid;
只要时间戳不能被valid整除,

false就会变为7。然后,根据&&的工作方式,它将永远保持false,并且由于&&是短路的,带有分配的方法doGenerate()永远不会得到再次打电话。

相比之下,在你的第二个变种中

boolean valid = true;
for (int i=0;i<1_000_000_000;i++) {
    long timeGenerated = System.currentTimeMillis();
    Address address = new Address(1021, "A Street", "A country", timeGenerated);
    valid = valid && address.isOk();
}
return valid;
只要时间戳不能被valid整除,

false也将成为并保持7,但唯一被短路的是调用{ {1}}。无论isOk()的值如何,都会发生构造。

原则上,valid的构造可以在这里消除,但这需要堆栈替换,因为它必须在循环运行时发生。目前尚不清楚这是否是问题,但更重要的结论是,在既不的情况下,我们看到EA发生,就像在第一种情况下,你没有调用包含分配的方法(之后)一个未知的,但预计会有少量的调用)。

因此,这两个例子并不等同,不允许得出关于逃逸分析的结论。