如果我有
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()
被调用的可能性?
答案 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;
}
}
}