垃圾收集器销毁对象后删除文件

Delete a file after object is destroyed by garbage collector

我的 class 的对象保存从外部数据库检索的信息。数据库中有一个 CLOB 类型的列,它有 1M 大小。我不希望对象将其保存在内存中。所以我只在对象的字段中保留保存信息的本地文件的路径。但我不希望这个文件是持久的。我希望在对象被垃圾收集器销毁后将其删除。如何在 Java 中实现?我想我的 class 应该扩展一些其他特定的 class 然后覆盖我明确删除文件的方法。

更新: 我正在使用 Java servlet 和 Apache Tomcat 制作动态 Web 应用程序。这个 webapp 与外部数据库一起工作。 Webapp 在 Linux 上运行。它具有某种分层架构,使用域、商店和 servlet。上述对象的生命周期只是在 servlet 中调用 doGet() 或 doPost() 方法的持续时间。

您想要覆盖 Object.finalize。这是气馁。为什么?参见 https://softwareengineering.stackexchange.com/questions/288715/is-overriding-object-finalize-really-bad

我们鼓励您在知道文件已完成后明确清理该文件。

我不会自己持久化和删除它,而是使用堆外直接 ByteBuffer 来存储数据。这有很多优点。

  • 这首先没有写入磁盘。
  • 无论应用程序如何死亡,它都会被清理。
  • 无论大小,对堆的影响都非常小(堆上只有ByteBuffer代理)
  • 您可以控制创建的数量。
  • ByteBuffer 确实使用了 finalize 但更轻量级的机制(仅适用于不使用 IO 的组件)
  • 如果您开始 运行 内存不足,此数据将交换到交换 space,对堆、GC 时间或 OS 的影响相对较小。即比使用堆的影响小得多,比写入文件的影响小。

例如

ByteBuffer bb = ByteBuffer.allocateDirect(1 << 20); // 1 MB.

来自书本Java In A Nutshell:

A finalize method in an object is the opposite of a constructor. While a constructor method performs initialization for an object, a finalizer method performs finalization for the object. Garbage collection automatically frees up the memory resources used by objects, but objects can hold other kinds of resources, such as open files and network connections. The garbage collector cannot free these resources for you, so you need to write a finalizer method for any object that needs to perform such tasks as closing files, terminating network connections, deleting temporary files, and so on.

protected void finalize() throws Throwable {
  // Invoke the finalizer of our superclass
  // We haven't discussed superclasses or this syntax yet
  super.finalize();

  // Delete a temporary file we were using
  // If the file doesn't exist or tempfile is null, this can throw
  // an exception, but that exception is ignored. 
  tempfile.delete();
}

我同意 Stephen 不鼓励覆盖 finalize(),因为它不可预测,而且通常是不必要的。永远不要在 finalize() 中做任何时间紧迫的事情。 永远不要依赖终结器来更新关键持久状态。 你可以做的是从外部数据库中按需检索对象并在工作完成时销毁它(可能在 finally 块中)。

我不认为对于您的用例来说,使用终结会很糟糕,因为尽快释放您持有的资源并不是那么重要。

话虽如此,我会使用 "weak set" 而不是最终确定。 每次创建一个引用该文件的新对象时,您都可以将其添加到弱集中。因为它是弱集,对象不再使用时会自动删除。

然后您可以安排一个作业,从临时文件夹中删除所有不在弱集中的文件。

此解决方案的成本是定期检查临时文件夹中的每个文件,但如果您没有数千个活动的 CLOB,这将不是问题。

优点是能够控制执行清理的频率。

作为一个不错的副作用,您还将获得一个活动 CLOB 列表。