9

有没有办法创建注册一个处理程序,该处理程序将在释放对某个对象的最后引用时准确调用?

一个例子是一个由物理数据文件支持的对象,一旦该对象变得未被引用,该文件应该被关闭然后重命名。如果不必在该对象上显式调用“关闭”方法就可以做到这一点,那就太好了。

我从 Weak/Phantom 参考区域了解到的所有通知机制仅表明通知将在某个时间点发生,但无法保证何时会发生……

4

7 回答 7

13

简而言之,没有。

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

于 2008-10-16T13:33:47.807 回答
4

根据我的理解,我已经寻找了一段时间来为 java 对象找到一个“析构函数”,没有办法知道你什么时候丢失了最后一个引用。Java 跟踪对对象的引用,但出于性能原因,仅在垃圾收集期间更新此信息。

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

于 2008-10-16T13:34:53.750 回答
4

我认为 WeakReference 可以满足您的要求。WeakReference 在弱可访问时立即被放入 ReferenceQueue(即所有强引用都消失了)。

请参阅Ethan Nicholas的这篇文章。

如果您担心某些引用在关闭时无法到达 ReferenceQueue,请保留所有已创建对象的列表(使用 Wea​​kReferences 或 PhantomReferences)。添加一个关闭挂钩,检查列表中是否有任何未完成的引用并执行您需要的任何操作。

于 2008-10-17T15:47:08.567 回答
2

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

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

于 2008-10-16T13:57:22.300 回答
2

如果您需要管理文件等外部资源,您可以在 java 中做的最好的事情是 close() 函数(无论您选择什么名称)。您可以将 finalize() 用作“腰带和吊带”保险单,但这具有不可预测的时机。所以你的主要防线需要是 close() 函数。

见我的回答你为什么要实现 finalize()?

于 2008-10-16T15:37:29.413 回答
0

这不能用 Java 完成——据我所知,它需要一个引用计数垃圾收集器。您是否考虑过根据需要打开和关闭对象的物理数据文件,而不是在对象的生命周期内保持打开状态?

于 2008-10-16T15:15:06.183 回答
-1

可以在您的对象中覆盖finalize(),但由于其他人提到的原因,这是有问题的。

对于您的具体示例,您可以看看使用类似的东西 File.deleteOnExit(),一旦VM退出,它将删除文件。

于 2008-10-16T14:34:28.963 回答