当我删除for循环时,我得到一个OutOfMemoryError
。当我使用for循环时,我没有得到任何错误。
有谁能帮我理解这种行为吗?
public class JavaMemoryPuzzlePolite {
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);
public void f() {
{
System.out.println(dataSize);
byte[] data = new byte[dataSize];
}
for (int i = 0; i < 1; 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) {
JavaMemoryPuzzlePolite jmp = new JavaMemoryPuzzlePolite();
jmp.f();
}
}
1条答案
按热度按时间cig3rfwq1#
f()
方法在解释的帧中执行。解释的帧的行为与JIT编译的帧不同。下面是它在没有for循环的伪代码中的外观:因此,在步骤#3中,您有
OutOfMemoryError
,因为旧的byte[]
数组仍然驻留在变量#1中。但是,添加for循环(实际上添加了一个i
变量)会使情况有所不同:这里,当您在步骤#5分配新数组时,第一个数组可能已经被垃圾收集。
请注意,JIT编译器可能表现得更聪明,在第一个数组未被使用时取消它与变量的链接(在您的特定情况下,它根本不会分配它)。
还要注意,在您的特定情况下,结果取决于java编译器。ECJ(Eclipse编译器)足够聪明,根本不会将第一个数组存储到变量中,因为它没有被使用。因此,即使没有for循环,您也不会在ECJ编译的类中获得
OutOfMemoryError
。要了解更多细节,您可以查看
javap
实用程序提供的字节码反汇编输出,并了解如何重用变量插槽。