我唯一知道的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.)
小智 11
我发现了一个实用且有用的用例,PhantomReference它是org.apache.commons.io.FileCleaningTracker在commons-io项目中.FileCleaningTracker将标记对象进行垃圾回收时删除物理文件.
需要注意的是Tracker扩展PhantomReference类的类.
这应该在 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 一样。但我的解决方案更通用一些。