最终确定期间对对象的引用

发布于 2024-07-24 09:21:57 字数 228 浏览 5 评论 0原文

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

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

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

What happens if you save a reference to the current object during the finalize call? For example:

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

Is the object garbage-collected, or not? What happens when you try to access bar.REFERENCE later?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

慵挽 2024-07-31 09:21:57

该对象不会被垃圾回收。 这就是所谓的“对象复活”。

你必须小心,一旦调用了终结器,gc就不会再次调用它,在某些环境(例如.NET)上,你可以重新注册终结器,但我不确定java

The object is not garbage collected. This is know as "Object resurrection".

You must be careful with that, once the finalizer is called the gc won't call it again, on some enviroments like .NET you can re-register the finalizer but i'm not sure about java

七秒鱼° 2024-07-31 09:21:57

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

If you absolutely must resurrect objects, this JavaWorld article suggests creating a fresh instance rather than resurrecting the instance being finalized because if the instance being finalized becomes eligible for collection again it will simply be collected (the finalizer won't be run again).

紫南 2024-07-31 09:21:57

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

This kind of thing is the reason why the use of finalize() is generally discouraged.

自此以后,行同陌路 2024-07-31 09:21:57

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

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

如果在 finalize() 方法内部抛出异常(例如,由于 barnull 而引发 NullPointerException ),那么最终确定过程就简单地终止。

注意正如其他人指出的那样..你的例子绝对是应该避免的。

The finalize() method may be invoked explicitly on the foo instance, or it may be invoked by the garbage collector when it tries to reclaim the storage occupied by that object.

If bar is a valid instance, it sets the REFERENCE field to the foo instance. From the garbage collector's point of view, this increases foo's reference count.

If an exception is thrown inside the finalize() method (e.g. such as a NullPointerException due to bar being null), then the finalization process simply terminates.

N.B. As others have pointed out.. your example is definitely something to be avoided.

画离情绘悲伤 2024-07-31 09:21:57

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

通常,如果您确实使用终结器,则应将声明保留为 @Override protected void Finalize() throws Throwable,以免干扰 API。 更好的是使用受保护的终结器,如《Effective Java 第一版》中所示。

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

Because Java is a safe language and platform, the memory is not freed. Also associated PhantomReferences will not be enqueued upon their ReferenceQueues. The VM will only ever call finalize on an object once. There's a nice state diagram in the JVM Spec.

Typically if you do use a finaliser, you should leave the declaration as @Override protected void finalize() throws Throwable, so as not to disturb the API. Even better use a guarded finaliser, as in Effective Java 1st Ed.

This particular trick hit the headlines (of the San Jose Mercury, anyway) when a group at Princeton used it to construct a custom ClassLoader from untrusted code. Although the spec has been slightly tightened (the Object constructor has to finish executing normally before the finaliser can be called - specified in J2SE 5.0, implemented in Java SE 6), this still remains a problem area. If you are designing an API, make sure sensitive classes cannot be subclasses and save yourself much grief.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文