Java允许写:
new PhantomReference(new Object(), null)
在这种情况下 new Object()
会被收集吗?
据我所知,虚引用是 finalize()
方法用法的替代方法。
在队列中出现引用后,我需要执行一些额外的操作,然后运行 clear()
java 文档保留:
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
永远不会入队是什么意思?
据我了解,这意味着在完成方法调用后,引用将不会添加到引用队列中。因此它可能导致:
1.对象内存会被立即清除
2.对象内存不会被清除
哪种情况正确?
最佳答案
好吧,正如您自己注意到的,PhantomReference
不会自动清除。这意味着只要您保持对 PhantomReference
的强引用,所指对象将保持幻象可达。作为documentation说:“通过幻象引用可访问的对象将一直存在,直到所有此类引用都被清除或它们自身变得不可访问。”
然而,考虑到对象何时无法访问(现在我说的是“幻影引用本身”)可能会导致许多意外。尤其是引用对象很可能不会提供有用的操作,随后将不再被触及。
由于没有队列的PhantomReference
永远不会入队,而且它的get()
方法总是返回null
,所以确实没有用.
那么为什么构造函数允许构造这样一个无用的对象呢?嗯,the documentation of the very first version (1.2)说明如果队列为 null
,它将抛出 NullPointerException
。这个声明一直持续到 1.4,然后是 Java 5是第一个版本,其中包含您可以构造一个没有队列的PhantomReference
,尽管它是无用的。我的猜测是,它总是继承了父类(super class)允许 null
队列的行为,这与文档相矛盾,而且发现得太晚了,所以决定保持兼容性并调整文档而不是而不是改变行为。
更难回答的问题是,为什么 PhantomReference
不会自动清除。文档只说幻影可达对象将保持不变,这是未被清除的结果,但没有解释为什么这有任何相关性。
这个问题已经brought up on SO ,但答案并不令人满意。它说“允许在对象被垃圾收集之前执行清理”,这甚至可能符合做出该设计决定的人的心态,但由于清理代码无法访问对象,它没有相关性是在回收对象之前还是之后执行。如上所述,由于此规则取决于 PhantomReference
对象的可达性,该对象受优化代码转换的影响,甚至可能出现对象与 PhantomReference< 一起回收的情况
清理代码完成之前的实例,没有任何人注意到。
我也找到了类似的question on the HotSpot developer mailing list回到 2013 年也没有答案。
有增强请求JDK-8071507改变这种行为并清除 PhantomReference
就像其他人一样,它的状态对于 Java 9 来说是“固定的”,事实上,its documentation现在声明它们像任何其他引用一样被清除。
不幸的是,这意味着我帖子开头的答案从 Java 9 开始是错误的。然后,new PhantomReference(new Object(), null)
将使新创建的 Object
实例立即符合垃圾回收条件,无论您是否保留对 PhantomReference
实例的强引用。
关于java - 带有空队列的 PhantomReference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41396051/