如何检测对象不再被引用

9
有没有一种方法可以创建一个处理程序,该处理程序在特定对象的最后一个引用被释放时准确调用?
例如,一个由物理数据文件支持的对象,一旦该对象变得无法引用,文件应该关闭,然后重命名。如果不必显式地调用该对象的“close”方法,那就太好了。
我所知道的所有来自Weak/Phantom reference领域的通知机制都只说明通知将在某个时间点发生,但不能保证何时发生...
7个回答

13

简而言之,不行。

Java规范明确禁止您知道最后一个引用何时被释放。JVM实现(和优化)依赖于此。没有钩子。


1
你能参考一下规范吗? - searchengine27

4

据我所知,我已经寻找了一段时间来查找Java对象的“析构函数”,但是没有办法知道何时失去最后一个引用。 Java跟踪对象的引用,但出于性能原因,仅在垃圾回收期间更新此信息。

最接近的方法是finalize方法,在垃圾回收期间应该被调用,但即使在那时也不能保证它会被调用。


4
我认为WeakReference可以满足您的需求。一旦弱引用不再有强引用(即弱可达),它就会被放入ReferenceQueue中。
请参阅Ethan Nicholas撰写的本文。
如果您担心某些引用在关闭时无法到达ReferenceQueue,请使用WeakReferences或PhantomReferences创建所有对象的列表。添加一个关闭挂钩,检查列表是否有未完成的引用,并执行所需的操作。

https://web.archive.org/web/20120216083820/http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html - Edward Falk

2

问题是,“如何在没有任何东西持有对象的引用的情况下实现这一点?”

即使您能够解决这个问题,比如使用我们称之为HandleManager的服务,HandleManager也必须创建一个新的对该对象的引用,以传递给您的处理程序。然后,您的处理程序可以(a)存储对它的引用,这会让期望销毁无引用对象的HandleManager感到困惑;或者(b)释放引用,这意味着最终引用再次被释放,这意味着Handler必须再次被调用....


2
如果您需要管理像文件这样的外部资源,Java 中最好的做法是使用 close() 函数(无论您选择什么名称)。您可以使用 finalize() 作为“腰带和吊裤带”的保险策略,但它的时间安排是不可预测的。因此,您的主要防线需要是 close() 函数。
请参见我的答案为什么会实现 finalize()?

0

这个问题似乎无法通过Java解决 -- 我认为需要一个引用计数垃圾收集器。你是否考虑过根据需要打开和关闭对象的物理数据文件,而不是在对象的生命周期内一直保持它处于打开状态?


1
你所描述的是一种可能的解决方法。如果有一种方式可以在需要时调用这些清理操作,那将是很好的。然而,这需要对象的客户端记得显式地进行清理,这可能会导致错误。 - VoidPointer

-1

你可以在你的对象中重写finalize(),但是这样做会有其他人提到的问题。

对于你具体的例子,你可以尝试使用像 File.deleteOnExit() 这样的东西,它会在 VM 退出时删除文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接