我正在阅读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显示内存消耗图表:
但是当我们运行以下代码时,
public class test {
public static void main(String a[]){
for(int i=0;i<1000000;i++){
for(int j=0;j<100000;j++){
}
}
}
}
JVisualVM呈现锯齿:
为什么会这样? 两种情况如何以及为什么gc触发限制都会改变?
答案 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
答案 1 :(得分:1)
原因是编译代码后的优化算法。在第一种情况下,因为你每次创建一个双精度而不保留它的记录。这将使程序不断使用GC。因此编译器优化了代码,因此使用的内存更少。空循环是一种特殊情况,因为许多程序员使用它来使一个线程等待。所以编译器不会尝试优化它。