你有没有在任何项目中使用过PhantomReference?

Rak*_*yal 82 java reference

我唯一知道的PhantomReference是,

  • 如果使用其get()方法,它将始终返回null而不是对象.有什么用?
  • 通过使用PhantomReference,可以确保无法从finalize方法中复活对象.

但是这个概念/类的用途是什么?

你有没有在你的任何项目中使用过这个,或者你有任何我们应该使用它的例子吗?

Pet*_*ler 46

PhantomReference在一个简单的,非常专业的内存分析器中使用s 来监视对象的创建和销毁.我需要他们来追踪破坏.但这种方法已经过时了.(它是在2004年针对J2SE 1.4编写的.)专业的分析工具功能更强大,更可靠,JMX或代理和JVMTI等新的Java 5功能也可用于此.

PhantomReferences(总是与参考队列一起使用)优于finalize其中存在一些问题,因此应该避免.主要是使对象再次可达.使用终结器监护人习语可以避免这种情况( - >在'Effective Java'中阅读更多内容).所以他们也是新的定型.

此外,PhantomReferences

允许您确定从内存中删除对象的确切时间.事实上,它们是确定这一点的唯一方法.这通常不是很有用,但在某些非常特殊的情况下可能会派上用场,例如操作大图像:如果你确定图像应该被垃圾收集,你可以等到它实际上是在尝试加载下一个图像之前,因此不太可能使可怕的OutOfMemoryError.(引自enicholas.)

正如psd首先写的那样,Roedy Green 对参考文献很好的总结.


小智 21

一个普通切块表的解释,从Java词汇.

当然,这与PhantomReference文档一致:

幻像引用对象,在收集器之后排队,确定可以回收它们的对象.幻像引用最常用于以比Java终结机制更灵活的方式调度预先清理操作.

最后但并非最不重要的是,所有的血腥细节(这是一个很好的阅读):Java参考对象(或我如何学会停止担心和爱OutOfMemoryError).

快乐的编码.(但要回答这个问题,我只使用过WeakReferences.)


Ser*_*hyk 13

Phantom参考用法的重要解释:

幻像引用是了解已从内存中删除对象的安全方法.例如,考虑处理大图像的应用程序.假设当大图像已经存储在已准备好收集垃圾的内存中时,我们想要将大图像加载到内存中.在这种情况下,我们希望等到收集旧图像之后再加载旧图像.在这里,幻像参考是灵活且安全的选择.一旦旧图像对象完成,旧图像的引用将在ReferenceQueue中排队.收到该引用后,我们可以将新映像加载到内存中.


小智 11

我发现了一个实用且有用的用例,PhantomReference它是org.apache.commons.io.FileCleaningTracker在commons-io项目中.FileCleaningTracker将标记对象进行垃圾回收时删除物理文件.
需要注意的是Tracker扩展PhantomReference类的类.


Cla*_*tin 6

这应该在 JAVA 9 中过时了!
使用java.util.Cleaner,而不是!(或sun.misc.Cleaner在较旧的 JRE 上)

原帖:


我发现 PhantomReferences 的使用与终结器方法有几乎相同数量的陷阱(但一旦你做对了,问题就会减少)。我为 Java 8 编写了一个小解决方案(一个使用 PhantomReferences 的非常小的框架)。它允许使用 lambda 表达式作为在对象被删除后运行的回调。您可以为应该关闭的内部资源注册回调。有了这个,我找到了一个对我有用的解决方案,因为它使它更实用。

https://github.com/claudemartin/java-cleanup

下面是一个小例子来展示回调是如何注册的:

  class Foo implements Cleanup {
    //...  
    public Foo() { 
    //...    
      this.registerCleanup((value) -> {
        try {
          // 'value' is 'this.resource'
          value.close();
        } catch (Exception e) {
          logger.warning("closing resource failed", e);
        }
      }, this.resource);
    }
Run Code Online (Sandbox Code Playgroud)

然后还有更简单的自动关闭方法,与上面的操作大致相同:

this.registerAutoClose(this.resource);
Run Code Online (Sandbox Code Playgroud)

回答您的问题:

【那有什么用】

你无法清理不存在的东西。但它可能有仍然存在的资源,需要清理,以便可以将其删除。

但是这个概念/类有什么用呢?

除了调试/记录之外,不一定要做任何有任何影响的事情。或者也许是为了统计。我认为它更像是来自 GC 的通知服务。您还可以使用它来删除对象被删除后变得不相关的聚合数据(但可能有更好的解决方案)。示例经常提到要关闭的数据库连接,但我不明白这是一个好主意,因为您无法使用事务。应用程序框架将为此提供更好的解决方案。

你有没有在你的任何项目中使用过这个,或者你有任何我们应该使用它的例子吗?或者这个概念只是为了面试的观点;)

我主要使用它来记录日志。所以我可以跟踪删除的元素,看看 GC 是如何工作的,并且可以进行调整。我不会以这种方式运行任何关键代码。如果需要关闭某些内容,则应在 try-with-resource-statement 中完成。我在单元测试中使用它,以确保我没有任何内存泄漏。和 jontejj 一样。但我的解决方案更通用一些。