在java中,空循环比非空循环消耗更多内存

时间:2014-08-20 10:57:53

标签: java memory-management jvm

我正在阅读java性能调优并遇到了这个问题。

当我们跑步时

public class test {
public static void main(String a[]){
    for(int i=0;i<1000000;i++){
        for(int j=0;j<100000;j++){
            Double d = new Double(1.0);
        }
    }
}
}

JVisualVM显示内存消耗图表:

enter image description here

但是当我们运行以下代码时,

public class test {
public static void main(String a[]){
    for(int i=0;i<1000000;i++){
        for(int j=0;j<100000;j++){
        }
    }
}
}

JVisualVM呈现锯齿:

enter image description here

为什么会这样? 两种情况如何以及为什么gc触发限制都会改变?

2 个答案:

答案 0 :(得分:2)

关于你的v1 for loops,你的本地变量,一旦退出其范围,它将被标记为GC可以自由收集,所以每隔一段时间GC就会启动并收集该内存。

对于你的v2 for loops,这些空循环不会被编译器**“优化掉”,只有在多次调用之后,因为

  

JIT在某段代码被执行多次后触发   时代[1]

关于你的锯齿形状,ruakh有一个很好的解释[2]:

  

如果我没有弄错,部分原因是监视器本身正在强制应用程序创建临时对象,其中包含有关垃圾收集和内存使用状态的信息。

**它们可能永远不会被删除,因为众所周知这些空循环被用作等待机制。*

[1] Java: how much time does an empty loop use? - Simone Gianni's answer

[2] Why does an empty Java program consume memory?

答案 1 :(得分:1)

原因是编译代码后的优化算法。在第一种情况下,因为你每次创建一个双精度而不保留它的记录。这将使程序不断使用GC。因此编译器优化了代码,因此使用的内存更少。空循环是一种特殊情况,因为许多程序员使用它来使一个线程等待。所以编译器不会尝试优化它。