带空队列的PhantomReference [英] PhantomReference with null queue

查看:165
本文介绍了带空队列的PhantomReference的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java允许编写:

$ p $ 新的PhantomReference(new Object(),null)

在这种情况下将会收集新的Object()吗?



据我所知,幻像引用是 finalize()方法的一种替代方法。



在队列中出现引用后,我需要执行一些额外的操作,然后运行 clear()



java文档保留:


可以用空队列创建幻影引用,但
这样的引用是完全的无用的:它的get方法总是
返回null,并且由于它没有队列,所以它永远不会被
入列


如果它永远不会入队,那意味着什么?

据我所知,这意味着finalize方法调用rerference不会被添加到referenceQueue。因此它可能导致:

1.对象内存将被立即清除

2.对象内存不会被清除

<那么正如你注意到的那样,一个 PhantomReference

$ c>不会自动清除。这意味着只要您保持对 PhantomReference 的强引用,指示对象将保持幻像可达。正如文档所述: 通过幻影引用可访问的对象将保持如此状态,直到所有这样的引用被清除或自己变得无法访问。

然而,考虑何时一个对象无法访问(现在我正在谈论幻影引用自己)可能会导致许多惊喜。特别是因为引用对象很可能不提供有用的操作,所以不会再被触摸了。


PhantomReference 永远不会被入队,它的 get()方法将总是返回 null ,这确实是没有用。



那么为什么构造函数允许构造这样一个无用的对象呢?那么,第一个版本(1.2)的文档指出它会抛出 NullPointerException 如果队列是 null 。此语句持续到1.4,然后 Java 5 是第一个包含可以构造 PhantomReference null 队列的行为,与文档相矛盾,并且它被注意到这么晚了,所以决定留下来兼容和适应文档,而不是改变行为。






这个问题更难回答,为什么 PhantomReference 不会自动清除。该文件只是说,一个幻像可到达对象将保持这样,这是未被清除的结果,但并不能解释为什么这有任何相关性。



这个问题已经提出来了,但答案并不令人满意。它表示在对象被垃圾收集之前允许执行清理,这甚至可以与做出该设计决定的人的思维相符,但由于清理代码无法访问该对象,因此它没有它是在对象被回收之前还是之后执行的相关性。如上所述,由于这个规则依赖于可以优化代码转换的 PhantomReference 对象的可达性,所以甚至可以将对象与清理代码完成之前的 PhantomReference 实例,没有任何人注意到。

我也发现了一个类似的 HotSpot开发者邮件列表上的问题早在2013年这也没有答案。



增强请求 JDK-8071507 可以更改该行为并清除 PhantomReference ,就像其他人一样,Java 9的状态为固定实际上,其文档ion 现在声称它们被清除,就像其他任何引用一样。



不幸的是,这意味着我的文章开头的答案是错误的,从Java开始9.然后, new PhantomReference(new Object(),null)将使新创建的 Object 实例立即符合条件垃圾收集,无论您是否保留对 PhantomReference 实例的强引用。


Java allow to write:

new PhantomReference(new Object(), null)

At this case new Object() will be collected?

As I understand, phantom reference is alternative of finalize() method usage.

And after appearing reference in queue, I need to do some additional actions and then run clear()

java doc stays:

It is possible to create a phantom reference with a null queue, but such a reference is completely useless: Its get method will always return null and, since it does not have a queue, it will never be enqueued

What does mean if it will never be enqueued?

As I understand it means that after finalize method invocation rerference will not be added to the referenceQueue. Thus it may lead to:
1. object memory will be cleared at once
2. Object memory will not be cleared

which case correct?

解决方案

Well, as you noticed yourself, a PhantomReference is not automatically cleared. This implies that as long as you keep a strong reference to the PhantomReference, the referent will stay phantom reachable. As the documentation says: "An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable."

However, considering when an object is unreachable (now I’m talking about the "phantom references themselves") can lead to many surprises. Especially as it’s very likely that the reference object, not providing useful operations, will not be subsequently touched anymore.

Since the PhantomReference without a queue will never be enqueued and its get() method will always return null, it is indeed not useful.

So why does the constructor allows to construct such a useless object? Well, the documentation of the very first version (1.2) states that it will throw a NullPointerException if the queue is null. This statement persists until 1.4, then Java 5 is the first version containing the statement that you can construct a PhantomReference without a queue, despite being useless. My guess is, that it always inherited the super class’ behavior of allowing a null queue, contradicting the documentation, and it was noticed so late, that the decision was made to stay compatible and adapt the documentation rather than changing the behavior.


The question, even harder to answer, is why a PhantomReference isn’t automatically cleared. The documentation only says that a phantom reachable object will remain so, which is the consequence of not being cleared, but doesn’t explain why this has any relevance.

This question has been brought up on SO, but the answer isn’t really satisfying. It says "to allow performing cleanup before an object is garbage collected", which might even match the mindset of whoever made that design decision, but since the cleanup code can’t access the object, it has no relevance whether it is executed before or after the object is reclaimed. As said above, since this rule depends on the reachability of the PhantomReference object, which is subject to optimizing code transformations, it might be even the case that the object is reclaimed together with the PhantomReference instance before the cleanup code completes, without anyone noticing.

I also found a similar question on the HotSpot developer mailing list back in 2013 which also lacks an answer.

There is the enhancement request JDK-8071507 to change that behavior and clear PhantomReferences just like the others, which has the status "fixed" for Java 9, and indeed, its documentation now states that they are cleared like any other reference.

This, unfortunately implies that the answer at the beginning of my post will be wrong starting with Java 9. Then, new PhantomReference(new Object(), null) will make the newly created Object instance immediately eligible for garbage collection, regardless of whether you keep a strong reference to the PhantomReference instance or not.

这篇关于带空队列的PhantomReference的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆