如何`finalize`调用打破GC / JVM?

时间:2012-12-25 12:20:12

标签: java

在调查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?

1 个答案:

答案 0 :(得分:9)

  

但是如何只有一个空的finalize调用会破坏GC / JVM?

当有一个终结器时,对象可以比其他方式更多地进行垃圾回收(因为对象本身必须保持活着直到它完成)。因此,如果你有一个带有终结器的大对象,那么在没有终结器的情况下自然会导致OutOfMemoryError发生。

在此代码中:

A a1 = new A();
a1 = null;
A a2 = new A();

... GC将在最后一行触发,以便尝试找到足够的内存来分配第二个A。不幸的是,它不能垃圾收集第一个A(以及它引用的数组),因为终结器还没有运行。它等到终结器完成,然后再次尝试垃圾回收 - 它只是抛出OutOfMemoryError