用Java替换finalize()

时间:2017-12-11 23:16:42

标签: garbage-collection java-9 finalizer

Java 9中不推荐使用

Object.finalize(),我想我理解其中的原因,但我很难看到如何替换它。

我有一个名为Configuration的实用程序类,它实际上有一个实例,该实例拥有应用程序中的所有内容并持续应用程序的持续时间。它提供的服务之一是日志记录:在第一次请求记录消息时,创建记录器(由于各种遗留原因,它是我自己的记录器而不是标准记录器),并且在字段中保存了引用。配置对象,以及在应用程序终止时,无论是正常还是异常,我想释放记录器所拥有的任何资源(这是一个黑盒子,因为我的库的用户可以提供他们自己的实现)。

目前,这是通过调用Configuration.finalize()的{​​{1}}方法实现的。

我应该做什么呢?

4 个答案:

答案 0 :(得分:6)

Phantom referencesfinalize()的一般替代品。 Java运行时的许多类已经在使用它们。

使用Phantom references有点费力,你必须维护自己的引用列表和事后处理线程。另一方面,你完全掌控。

幻影参考设置的

Here is a simple example

This article解释并比较了Java finalize()Phantom references的实现。

答案 1 :(得分:6)

Java 9引入了Cleaner和Cleanable实用程序类,它们负责将虚拟引用连接到队列和清理该队列的清理线程。

虽然这可以让你在拥有对象死亡后分离出将要进行事后清理的证人,但所有关于GC触发的资源管理的警告仍然适用,即仍然可以依赖{{1}和try-with-resources块来管理资源的生命周期,而不是垃圾收集器。

答案 2 :(得分:3)

您可以将线程shutdown hook添加到运行时:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    // cleanup code
}));

当VM终止时调用此函数,因此在您的特定情况下它应该是finalize的良好替代

答案 3 :(得分:2)

恕我直言,你的应用程序不负责告诉记录器清理它自己的烂摊子。记录器本身可以和 这样做(与IO流或数据库连接不同),它应该活得很长。

但您已提供logger.close() ...好的,我建议如下:

  • 确保close是幂等的,即第二次关闭记录器是无操作。
  • 同时使用Runtime#addShutdownHookPhantomReference,让他们都调用logger.close(),以便在JVM终止或您的应用程序获得GC时调用它。< / LI>