在finalize()之后可以调用其他方法吗?

时间:2016-06-13 18:32:11

标签: java finalize

如果我有

public class Foo {
    private boolean finalized = false;

    public void foo() {
        if (finalized)
            throw new IllegalStateException("finalize() has been called.");
    }

    @Override public void finalize() {
        super.finalize();
        finalized = true;
    }
}

是否有保证,即使面对多个线程,假设只有GC会调用finalize()IllegalStateException永远不会被抛出?

我知道,面对导致对象不可垃圾收集的finalize()方法,对象不会被垃圾收集,并且可能会调用其他方法。但是这finalize()并没有这样做。 foo()之后是否还有finalize()被调用的可能性?

2 个答案:

答案 0 :(得分:7)

完全可能的是,同时最终确定了对Foo实例的引用的不同的对象 - 并且可能会复活{{1}对象,允许在完成后使用它。这有点粗鲁,但肯定会发生。

即使没有复活,另一个终结者也可以从终结者中调用Foo

Foo.foo()

答案 1 :(得分:0)

正如Jon Skeet所提到的,当一个线程目前处于最终化过程中时,完全有可能调用方法。

为了防范这种情况,您当然可以使代码成为线程安全的。

public class Foo {
    private boolean finalized = false;

    public void foo() {
        synchronized (this)
        {
            if (finalized)
                throw new IllegalStateException("finalize() has been called.");
        }
    }

    @Override public void finalize() {

        synchronized (this)
        {
            super.finalize();
            finalized = true;
        }
    }
}

注意:为了格外小心,我会在try / finally块中调用super.finalize():

@Override public void finalize() {

        synchronized (this)
        {
            try
            {
                super.finalize();
            }
            finally
            {
                finalized = true;
            }
        }
    }