java - 带有空队列的 PhantomReference

标签 java garbage-collection finalize finalization phantom-reference

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/

相关文章:

garbage-collection - 如何在没有 gc 的情况下实现闭包?

wcf - 垃圾回收后 WCF 中 COM 对象的访问冲突

java - 有没有办法强制执行finalize()方法

java - 我是否会在使用 PhantomReferences 完成时避免使用反射?

java - 如何知道 x509 证书是否由 RSA 签名?

java - 哪些版本的 java 对于 gc 日志记录很慢?

java - 有什么方法可以检查 RedisTemplate 是否存在 key ?

java - java中的内存泄漏

java.io.IOException : Stream closed During PDFbox setValue loop 异常

java - 使用jpcap读取数据包头