我在我的java程序中发现了一个奇怪的行为,我的代码看起来像这样
public class JavaTest {
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);
public void test() {
{
System.out.println(dataSize);
byte[] data = new byte[dataSize];
}
// for (int i = 0; i < 10; i++) {
// System.out.println("Please be so kind and release memory");
// }
System.out.println(dataSize);
byte[] data2 = new byte[dataSize];
}
public static void main(String[] args) {
JavaTest jmp = new JavaTest();
jmp.test();
}
}
在这里,当我评论for
循环时,我得到Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
,我可以理解jvm堆sapce已满。
但在我的代码中使用for
循环,它会正确执行。怎么来的?
答案 0 :(得分:6)
我认为这是因为你在byte[] data
块中声明{ }
,这意味着当代码块结束时data
的范围结束。在循环取消注释的情况下,您可能会给垃圾收集器留出时间来释放data
占用的内存。当你注释掉循环时,GC还没有时间释放内存。
如果您在{ }
声明周围移除data
,即使循环取消注释,它也会抛出OutOfMemoryException
。
<强>更新强>
@SubOptimal在评论中提到的{p> This blog post证明这个理论是错误的,看起来它与GC释放内存所需的时间没有任何关系。我将引用博客中的相关部分大多数回复都不正确,并建议for()循环要么让GC时间在System.out.println()...
期间完成其工作。我的一些读者意识到它与System.out.println无关,而且一个简单的int i = 0;就够了如果在代码块之后立即声明任何局部变量,则在第二次调用新字节[]之前,中断对堆栈帧中保存的byte []的强引用 1。