【问题标题】:When a PhantomReference/SoftReference/WeakReference is queued, how do you know what it referred to?当 PhantomReference/SoftReference/WeakReference 排队时,你怎么知道它指的是什么?
【发布时间】:2011-12-03 09:40:31
【问题描述】:

我没有使用 PhantomReferences。实际使用的好例子似乎很少。

当一个幻影出现在您的队列中时,您如何知道它是/曾经是哪个对象? get() 方法似乎没用。根据the JavaDoc

因为虚引用的所指对象总是不可访问的, 此方法始终返回 null。

我认为,除非您的对象是单例,否则您总是希望使用 PhantomReference 的 子类,您可以在其中放置所需的任何纪念品以了解死亡的原因。

这是正确的,还是我错过了什么?

对于软引用也是如此吗? 对于弱引用?

相关使用示例的链接会很棒。

【问题讨论】:

  • 我第一次也是最后一次遇到幻像引用是在我攻读学位期间,我的主管认为它们几乎没用。
  • 我想知道他是否考虑过对引用进行子类化。
  • @lynks,它们不是没用的,你可以用它们创建你自己的终结器。使用一些可运行的(实现或引用)进行子类化,这是一种常见的方式。或者,您可以使用身份映射 Phantom->Runnable。 sun.misc.Clearner 是在 java 1.4 中引入的,有利于终结,所有 DirectBuffers 都使用它。

标签: java weak-references soft-references phantom-reference


【解决方案1】:

我认为,除非您的对象是单例,否则您总是希望使用 PhantomReference 的子类,您可以在其中放置所需的任何纪念品,以便了解死亡的原因。

您还可以使用Map<Reference<?>, SomeMetadataClassOrInterface> 来恢复您需要的任何元数据。由于ReferenceQueue<T> 返回Reference<T>,您要么必须将其转换为您期望的PhantomReference 的任何子类,要么让Map<> 为您完成。

不管怎样,使用 PhantomReferences 似乎会给您带来一些负担:

与软引用和弱引用不同,幻像引用在排队时不会被垃圾收集器自动清除。通过幻像引用可访问的对象将保持不变,直到所有此类引用都被清除或自身变得不可访问。

因此您必须自己 clear() 引用才能回收内存。 (为什么必须这样做而不是让 JVM 为你做这件事是有用的)

【讨论】:

  • 谢谢,杰森。我能想到的唯一好的场景是某种 JNI 实现的异步数据源正在写入被引用的对象,并且必须在内存回收之前被告知停止。在这种情况下,如果没有像 Phantom 这样的机制,一个简单的 forgot-to-dispose() 错误可能会导致内存损坏。另一种表达方式是,这是对 finalize() 的更好替代。有意义吗?
  • ahhh... 从来没有想过 JNI 封装的代码使用 JVM 分配的内存的情况。除此之外,似乎没有任何理由延迟特定内存块的垃圾收集。
【解决方案2】:

您的问题使我对其进行了更多研究,我发现了这个写得很好的解释和所有参考类型的示例。他甚至谈到了幻影引用的一些(微不足道的)用途。

http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 2018-01-21
    • 1970-01-01
    • 2010-09-22
    • 2018-07-23
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    相关资源
    最近更新 更多