【发布时间】:2018-08-19 10:31:54
【问题描述】:
这是我试图从Java Performance: The Definitive Guide, Page 97 复制的关于逃逸分析 主题的示例。这可能是应该发生的事情:
-
getSum()必须足够热,并且必须使用适当的 JVM 参数将其内联到调用者main()。 - 由于
list和sum变量都不会从main()方法中逃脱,它们可以标记为NoEscape,因此JVM 可以为它们使用堆栈分配而不是堆分配。
但我通过jitwatch 运行它,结果显示getSum() 编译成本机程序集并且没有内联到main()。更不用说因此堆栈分配也没有发生。
我在这里做错了什么? (我已经把整个代码和热点日志here放好了。)
代码如下:
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.stream.IntStream;
public class EscapeAnalysisTest {
private static class Sum {
private BigInteger sum;
private int n;
Sum(int n) {
this.n = n;
}
synchronized final BigInteger getSum() {
if (sum == null) {
sum = BigInteger.ZERO;
for (int i = 0; i < n; i++) {
sum = sum.add(BigInteger.valueOf(i));
}
}
return sum;
}
}
public static void main(String[] args) {
ArrayList<BigInteger> list = new ArrayList<>();
for (int i = 1; i < 1000; i++) {
Sum sum = new Sum(i);
list.add(sum.getSum());
}
System.out.println(list.get(list.size() - 1));
}
}
我使用的JVM参数:
-server
-verbose:gc
-XX:+UnlockDiagnosticVMOptions
-XX:+TraceClassLoading
-XX:MaxInlineSize=60
-XX:+PrintAssembly
-XX:+LogCompilation
【问题讨论】:
-
synchronized可能是一个原因。 -
@Henry 我试图从书中复制,但我也尝试过不同步但仍然无法内联。
-
很有趣,但我在你的日志中看到这样的条目
task_queued compile_id='37' compile_kind='osr',好像osr是被踢了 -
是的@Eugene,getSum 方法被编译到本机程序集中。但我期待别的东西(我在问题中描述过)
-
你的循环运行在
main方法中,所以只能通过OSR切换到优化版本。众所周知,这是有局限性的。
标签: java jit jvm-hotspot escape-analysis