8

在 java 中,如果没有指向 x 的强引用并且 x 有资格进行垃圾收集,那么垃圾收集将在对象 x 上调用 finalize 方法。如果 finalize 方法永远不会终止,这会导致内存泄漏吗?

公共课 X{
  受保护的无效finalize(){
     而(真){}
  }
}
4

4 回答 4

6

是的,很容易测试

public class X {

    protected void finalize() {
        while (true) {
        }
    }

    public static void main(String[] args) throws Exception {
        while (true) {
            new X();
        }
    }
}

过了一段时间我得到了

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"

当我删除 finalize() 时,测试从未停止过。请注意,在 JVM 进入 OOM 之前需要一段时间

顺便说一句,运行这个测试就足够了

public class X {
    byte[] a = new byte[100 * 1000 * 1000];

    protected void finalize() {
        System.out.println();
    }

    public static void main(String[] args) throws Exception {
        while (true) {
            new X();
        }
    }
}

打破GC

Exception in thread "main" 
java.lang.OutOfMemoryError: Java heap space
    at test.X.<init>(X.java:5)
    at test.X.main(X.java:13)

注释掉 //System.out.println(); 它不停地工作

于 2013-01-24T11:15:21.593 回答
2

是的。
同样在 finalize 方法中,如果您对调用 finalize 方法的对象提供有效引用,Java 不会垃圾收集该对象,也不会再次调用 finalize 方法,因为它只被调用一次。

于 2013-01-24T11:12:05.493 回答
2

绝对。内存将在 finalize 方法返回后被释放。如果你的 finalize 永远不会返回,moory 将不会被释放。

谷歌关于垃圾回收中的复活,你会得到 finalize 方法不能保证 gc 的各种实例

于 2013-01-24T11:13:58.913 回答
0

它会阻塞 java.lang.ref.Finalizer$FinalizerThread (The Secret Life Of The Finalizer),所有实现 finalize 方法的类的实例都会被阻塞在 java.lang.ref.Finalizer.ReferenceQueue 中。您继续使用“finalize”创建新对象,那些等待执行 finalize 的对象将耗尽内存。如果进行堆转储,您会看到 java.lang.ref.Finalizer 保留了对象,请参见下面的示例(这是一个真实案例)。在此处输入图像描述

于 2013-02-22T01:49:55.083 回答