我发现this example code为Joshua Bloch 's book, Effective Java. It' s意味着要证明为什么你应该避免不必要地创建对象:
public class Sum {
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}
public static void main(String[] args) {
int numSets = Integer.parseInt(args[0]);
long x = 0;
for (int i = 0; i < numSets; i++) {
long start = System.nanoTime();
x += sum();
long end = System.nanoTime();
System.out.println((end - start) / 1_000_000. + " ms.");
}
// Prevents VM from optimizing away everything.
if (x == 42)
System.out.println();
}
}
主要方法的最后两行在这里完成了什么?
3 回答
最后的比较是该变量的唯一用法 . 没有它,谁会关心那个变量的 Value ?
没有人!
因此,编译器可能会假设:该值永远不会被使用,并且写入它的代码具有节点副作用 . 不习惯的事情,为什么浪费时间写信给他们 .
因此:最后的第一个“读取”用法可防止过度急切的compilerd“优化”对您要测量的方法的调用!
最后两行强制编译器运行整个循环,以找到
x
的值 . 否则它可能会检测到x
根本没有被使用而忽略了循环,因为它内部没有"real"工作 . 即使重复调用sum()
,如果我们对x
什么都不做,那么累积其返回值的结果最终会被丢弃 .当然,这假设循环中的
println()
语句可以安全地忽略,我不确定编译器是否可以做出这样的决定 . 那将是一个积极的编译器!最后两行将确保JVM不会删除它可能会考虑无操作的调用,否则,一个选项是使用结果 - 因此您可以对所有返回值求和,然后在结尾显示总和 .
阻止vm优化的另一种方法是禁用JIT:
JIT: