finalize()方法没有被调用

3

为什么这里没有调用finalize()方法。代码编译和运行成功,但没有任何输出。

package temp;

public class Temp {

    int i;

    Temp(int j) {
        i = j;
    }

    public void finalize() {
        if (i == 10) {
            System.out.println("Finalize called.");
        }
    }

    public static void main(String[] args) {
        Temp obj = new Temp(10);
        System.gc();
    }

}

请参考以下链接:https://dev59.com/anE95IYBdhLWcg3wAo9U - Vishal Zanzrukia
1
不保证实际执行垃圾回收。 - Raghu
4个回答

6

您调用 System.gc(); 没有任何作用,因为您的 Temp 实例具有引用(obj),因此它不符合垃圾回收的条件。

即使它符合垃圾回收的条件,调用 System.gc(); 也不一定会立即回收所有没有引用的对象。


3
即使调用了System.gc(),也不能保证进行垃圾回收。因此,可能不会调用finalize方法。 - Sid
1
事实上,没有任何保证。System.gc() 只是建议运行垃圾回收。 - Secondo

2
恰好我正在阅读《Effective Java》(Effective Java)。 条款7:避免使用finalizers

Finalizers是不可预测的,通常很危险,并且通常是不必要的。——《Effective Java》(第50页)

另一个来自PDF文件的引用:

不要被System.gc和System.runFinalization方法所迷惑。它们可能会增加执行finalizers的机会,但它们并不能保证这一点。唯一声称能够保证终结的方法是System.runFinalizersOnExit及其邪恶的孪生兄弟Runtime.runFinalizersOnExit。这些方法存在致命缺陷,并已被废弃[ThreadStop]。

基于此,使用System.gc只会增加finalizers被执行的机会,而且重要的是,使用它并不能保证运行垃圾回收,它只是向JVM提出了建议。
还有另外一段话。
语言规范不仅不能保证finalize方法会被及时执行,而且也不能保证它们会被执行。很有可能程序在终止时没有对一些不再可达的对象执行finalize方法。

0

添加 obj = null; 使引用为空,然后您的 finalize 方法将被调用。这仍不是一种可保证的行为,对我来说,我在 5 次中能够 1-2 次调用它。

 public static void main(String[] args) {
        Temp obj = new Temp(10);
        obj  = null;
        System.gc();
    }

输出

hi10
Finalize called.

3
再次强调我在另一条评论中提到的,System.gc() 不保证垃圾回收。这取决于运行时的决策。在这种情况下它被触发了,但在其他时间可能不会。因此,这不是调用 finalize 的确定方法。 - Sid
@reto 是的,正确的,这只是使引用为空的一种可能性,但仍然不是保证。 :) - Ankur Singhal
我尝试了你说的方法 - 将引用设置为null。但这也不会调用finalize。我认为Sid上面所说的确实是正确的。只是没有一种确定的方法来调用finalize()。 - daft300punk
@AbhilashSingh,我也同意他的观点。我运行了我的代码,每5次中有一两次我能够调用finalize方法,输出确实出现了。 - Ankur Singhal

0
在创建对象时会调用构造函数而不是finalise()方法,因此您需要从实例obj中引用该函数,并且这里的System.gc();没有产生任何区别或调用了finalize()方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接