Here's the example I tried to reproduce from Java Performance: The Definitive Guide, Page 97 on the topic of Escape Analysis. This is probably what should happen:
getSum()
must get hot enough and with appropriate JVM parameters it must be inlined into the callermain()
.- As both
list
andsum
variables do not escape frommain()
method they could be marked asNoEscape
hence JVM could use stack-allocation for them instead of heap-allocation.
But I ran it through jitwatch and the result showed that getSum()
compiles into native-assembly and doesn't get inlined into main()
. Not to mention consequently stack-allocation didn't happen either.
What am I doing wrong in here ? (I have put the whole code and hotspot log here.)
Here's the code:
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 parameters I used:
-server
-verbose:gc
-XX:+UnlockDiagnosticVMOptions
-XX:+TraceClassLoading
-XX:MaxInlineSize=60
-XX:+PrintAssembly
-XX:+LogCompilation
synchronized
may be a reason. – Momentoustask_queued compile_id='37' compile_kind='osr'
, seems likeosr
is kicked in – Storkmain
method, so it can only switch to an optimized version via OSR. This is known to have limitations. – Artillery