如果Java finalize方法中存在无限循环或死锁,那么Finalizer线程会做什么

and*_*ndy 14 java multithreading finalize finalizer

如果Java finalize方法中存在无限循环或死锁,那么Finalizer线程会做什么.

mer*_*ike 16

规范写道:

在垃圾收集器回收对象的存储之前,Java虚拟机将调用该对象的终结器.

Java编程语言没有指定调用终结器的时间,除非说它将在重用对象的存储之前发生.

我读到这意味着终结者必须在存储可以重复使用之前完成.

Java编程语言没有指定哪个线程将为任何给定对象调用终结器.

重要的是要注意许多终结器线程可能是活动的(有时在大型共享内存多处理器上需要),并且如果大型连接数据结构变为垃圾,则可以调用该数据结构中每个对象的所有finalize方法同时,每个终结器调用在不同的线程中运行.

也就是说,最终化可能发生在垃圾收集器线程中,单独的thead中,甚至是单独的线程池中.

JVM不允许简单地中止执行终结器,并且只能使用有限数量的线程(线程是操作系统资源,操作系统不支持任意多个线程).因此,非终止终结器必然会使该线程池匮乏,从而禁止收集任何可终结的对象,并导致内存泄漏.

以下测试程序确认了此行为:

public class Test {

    byte[] memoryHog = new byte[1024 * 1024];

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Finalizing " + this + " in thread " + Thread.currentThread());
        for (;;);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            new Test();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在Oracle JDK 7上,它打印:

Finalizing tools.Test@1f1fba0 in thread Thread[Finalizer,8,system]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at tools.Test.<init>(Test.java:5)
        at tools.Test.main(Test.java:15)
Run Code Online (Sandbox Code Playgroud)