在finalize期间引用对象

如果在finalize调用期间保存对当前对象的引用会发生什么? 例如:

class foo { ... public void finalize() { bar.REFERENCE = this; } } 

对象是否被垃圾收集? 当您尝试访问bar.REFERENCE时会发生什么。稍后会bar.REFERENCE吗?

该对象不是垃圾回收。 这被称为“物体复活”。

你必须小心,一旦调用终结器,gc将不会再次调用它,在.NET等一些环境中你可以重新注册终结器,但我不确定java

如果你绝对必须复活对象,这篇JavaWorld文章建议创建一个新实例而不是复活正在最终确定的实例,因为如果最终确定的实例再次符合收集资格,它将被简单地收集(终结器将不再运行)。

这种事情是为什么通常不鼓励使用finalize()的原因。

因为Java是一种安全的语言和平台,所以内存不会被释放。 此外,相关的PhantomReference不会在其ReferenceQueue上排队。 VM只会在一次对象上调用finalize 。 JVM规范中有一个很好的状态图。

通常,如果您使用终结器,则应将声明保留为@Override protected void finalize() throws Throwable ,以免干扰API。 甚至更好地使用受保护的终结器,如Effective Java 1st Ed。

当普林斯顿的一个小组使用它从不受信任的代码构建自定义的ClassLoader时,这个特殊的技巧成为头条新闻(无论如何都是圣何塞水星)。 尽管规范略微收紧( Object构造函数必须在调用终结器之前正常执行 – 在J2SE 5.0中指定,在Java SE 6中实现),但这仍然是一个问题区域。 如果您正在设计API,请确保敏感类不能成为子类并为您节省很多麻烦。

可以在foo实例上显式调用finalize()方法,或者当垃圾收集器尝试回收该对象占用的存储时,可以调用它。

如果bar是有效实例,则它将REFERENCE字段设置为foo实例。 从垃圾收集器的角度来看,这会增加foo的引用计数。

如果在finalize()方法中抛出exception(例如由于barnull而导致的NullPointerException ),则终结过程将终止。

NB正如其他人所指出的那样……你的例子肯定是值得避免的。