在调查Why ThreadPoolExecutor behaves differently when running Java program in Eclipse and from command line?时,我写了一个测试,抛出一个非常奇怪的OutOfMemoryError(max mem = 256 Mb)
class A {
byte[] buf = new byte[150_000_000];
protected void finalize() {
int i = 1;
}
}
A a1 = new A();
a1 = null;
A a2 = new A();
注释int i = 1
并且测试有效。据我所知,当finalize
为空时,HotSpot会忽略它。但是,如何只有一个空的finalize
调用会破坏GC / JVM?
答案 0 :(得分:9)
但是如何只有一个空的finalize调用会破坏GC / JVM?
当有一个终结器时,对象可以比其他方式更多地进行垃圾回收(因为对象本身必须保持活着直到它完成)。因此,如果你有一个带有终结器的大对象,那么在没有终结器的情况下自然会导致OutOfMemoryError
发生。
在此代码中:
A a1 = new A();
a1 = null;
A a2 = new A();
... GC将在最后一行触发,以便尝试找到足够的内存来分配第二个A
。不幸的是,它不能垃圾收集第一个A
(以及它引用的数组),因为终结器还没有运行。它不等到终结器完成,然后再次尝试垃圾回收 - 它只是抛出OutOfMemoryError
。