如果在 finalize 调用期间保存对当前对象的引用会发生什么?例如:
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
对象是否被垃圾收集?当您稍后尝试访问时会发生什么bar.REFERENCE
?
如果在 finalize 调用期间保存对当前对象的引用会发生什么?例如:
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
对象是否被垃圾收集?当您稍后尝试访问时会发生什么bar.REFERENCE
?
该对象没有被垃圾回收。这被称为“对象复活”。
您必须小心,一旦调用终结器,gc 就不会再次调用它,在.NET 等某些环境中,您可以重新注册终结器,但我不确定 java
如果您绝对必须复活对象,这篇JavaWorld文章建议创建一个新实例而不是复活正在终结的实例,因为如果正在终结的实例再次符合收集条件,它将被简单地收集(终结器不会再次运行)。
这种东西finalize()
是一般不鼓励使用的原因。
该finalize()
方法可以在foo
实例上显式调用,也可以由垃圾收集器在尝试回收该对象占用的存储空间时调用。
如果bar
是有效实例,则将REFERENCE
字段设置为foo
实例。从垃圾收集器的角度来看,这增加了foo
的引用计数。
如果在方法内部抛出异常finalize()
(例如,NullPointerException
由于bar
being null
),则终结过程简单地终止。
注意正如其他人指出的那样..您的示例绝对是要避免的。
因为 Java 是一种安全的语言和平台,所以不会释放内存。关联PhantomReference
的 s 也不会在他们ReferenceQueue
的 s 上排队。VM 只会调用finalize
一次对象。JVM Spec 中有一个很好的状态图。
通常,如果您确实使用终结器,则应将声明保留为@Override protected void finalize() throws Throwable
,以免干扰 API。最好使用受保护的终结器,如 Effective Java 1st Ed 中。
ClassLoader
当普林斯顿大学的一个小组使用它从不受信任的代码构建自定义时,这个特殊的技巧成为头条新闻(无论如何是圣何塞水星) 。尽管规范已经略微收紧(Object
构造函数必须在调用终结器之前正常执行 - 在 J2SE 5.0 中指定,在 Java SE 6 中实现),但这仍然是一个问题区域。如果您正在设计一个 API,请确保敏感类不能是子类,以免给自己带来很多麻烦。