6

嗨,我在 java 中使用了很多临时文件,我的问题是它们没有被删除。

无需实现我自己的临时文件管理处理(我承认你并不难,但我很懒,还有很多事情要做,如果我可以节省为此更好地重新发明轮子)有没有办法确保临时文件磁盘上的内容将以相当常规的方式被删除。

1 - 使用 File tmp = File.createTempFile(),当然我可以说 tmp.deleteOnExit() 但是如果事情在服务中运行,它退出的唯一方式是当它崩溃(很少发生)或系统崩溃时(就像驱动器完全充满临时文件并推翻集群时......哎呀!)

理想情况下,垃圾收集器会在某个时间点收集创建的实例,并且由于应用程序中有很多空闲时间,如果 GC 可以完成清理并实际删除磁盘以及从内存中取消引用实例时。

我现在看到的唯一方法是重载 File 类并添加一个最终方法......如果我这样做,还不如使用我自己的临时文件管理器!

长话短说,我也可以使用垃圾收集器来清理系统资源(即文件)吗?


谢谢大家的答案。我接受了 Christoffer 的方法,因为它是最容易实现的,也是我最终要做的。

我想经过这么多年的清理工作让我忘记了在 C++ 的好日子里我本以为要努力做的基本家务。

4

7 回答 7

3

你当然可以。问题是你是否真的想要:)

我实际上在野外遇到过这个问题。正如您所注意到的,在运行服务而不是应用程序时,使用 deleteOnExit() 清理临时文件是没有用的。我发现最稳定的解决方案是重组程序流程,以便在每个任务的基础上创建临时文件,并在不再需要时显式删除。

如果您以任何其他方式执行此操作,即如果程序在执行期间的任何时候都无法断定是否应该保留或丢弃临时文件,则可能存在设计问题。在某些管理器工具中包装文件只会推迟“真正的”解决方案;)

于 2009-06-29T08:23:35.800 回答
2

您可能想查看PhantomReference

幻像引用对象,在收集器确定它们的引用对象可能会被回收后排队。幻影引用最常用于以比 Java 终结机制更灵活的方式调度事前清理操作。

于 2009-06-29T07:54:34.097 回答
2

当你的类被销毁时依靠事件触发并不是万无一失的,并且可能会留下文件。

我认为实现临时文件清理的最简单和最可靠的方法如下:

  • 为您的程序关闭时编写一个事件处理程序,以清理您在当前会话期间打开的所有文件。
  • 编写一个在程序启动时运行的程序,该程序将删除此文件夹中超过 24 小时的任何临时文件。

使用这种方法,您不必担心程序是否因某种原因崩溃并留下临时文件,并且您也不必担心程序会删除仍在使用的文件。

于 2009-06-29T07:57:41.233 回答
1

垃圾收集是此类信息处理的错误命名空间。

以下几点应该足以处理临时文件。

  1. 您应该尝试在不再使用该文件后直接删除该文件。finalize 块可以处理这个问题。

  2. 您应该使用 DeleteOnExit。

  3. 您可以在特殊的临时目录中创建临时文件。您可以在应用程序启动和关闭时删除此临时目录,以确保在应用程序关闭后不存在临时文件。

于 2009-06-29T07:58:24.323 回答
1

垃圾收集器对此类事情没有用。它是为内存管理而设计的,可能有很多缺点。

  • 文件不再使用后,您的对象可能会被收集很长时间。
  • 您的对象根本无法保证被收集。

这两件事都特别经常发生,如果 Java 以大堆大小开始 - 这在服务器端并不罕见。

在您的程序中的某个时刻,您必须关闭该文件上的 Streams(否则您会吃掉系统文件句柄,这会使系统无法使用,我已经这样做了)。在您关闭流时,您还可以删除关联的文件。这是最干净的方法。

于 2009-06-29T08:31:52.600 回答
0

那么你可以为一个文件制作一个包装器,当对象被垃圾收集时,它使用终结器来删除你的文件。

但是终结器不会以任何可预测的方式被调用,所以我真的不建议这样做。

于 2009-06-29T08:04:18.273 回答
0

垃圾收集器不是释放这种资源的地方。请参阅下面这两篇关于如何在 Java 中释放资源的文章 http://c2.com/cgi/wiki?ReleasingResourcesInJava 以及 Java 终结器的性能问题。他们可能会就如何使用它提供一些见解和理解。 http://www.enyo.de/fw/notes/java-gc-finalizers.html

于 2009-06-29T08:16:01.307 回答