12

在调查为什么 ThreadPoolExecutor 在 Eclipse 和命令行中运行 Java 程序时表现不同?我写了一个测试,抛出一个非常奇怪的 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 呢?

4

1 回答 1

9

但是一个空的 finalize 调用怎么会破坏 GC/JVM 呢?

当有终结器时,对象会比其他情况下多存活一轮垃圾收集(因为对象本身必须保持活动状态,直到它被终结)。因此,如果您有一个带有终结器的大对象,那自然会导致OutOfMemoryError在没有终结器的情况下发生。

在这段代码中:

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

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

于 2012-12-25T12:27:01.380 回答