【问题标题】:How to use garbage collection to delete files?如何使用垃圾回收来删除文件?
【发布时间】:2009-06-29 07:44:49
【问题描述】:

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

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

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

理想情况下,创建的实例会在某个时候被垃圾收集器收集起来,并且由于应用程序中有很多空闲时间,如果 GC 能够完成它的清理并实际删除,那就太棒了当从内存中取消引用实例时,磁盘上的文件也是如此。

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

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


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

我想在这么多年之后被清理干净让我忘记了基本的家务,我认为在 C++ 的好日子里,我是艰难的。

【问题讨论】:

  • 我认为您混淆了您的条款。垃圾收集器用于内存,而不是文件。
  • 更不用说,如果您希望它在应用程序退出时运行,您将不得不在其中手动放置一些东西,因为垃圾收集不会在退出/崩溃时运行(内存由那时的操作系统,而不是框架)
  • 而且 Java 没有析构函数,因此您无法将删除与收集的对象相关联。
  • 我知道垃圾收集器是做什么的,我想知道我是否可以以某种方式扩展它的影响区域并删除磁盘上的实际文件以及内存实例,它毕竟是一个临时文件...
  • @lhahne:臭名昭著的“finalize()”不是几乎等同于 Java 中的析构函数吗?

标签: java temporary-files garbage-collection


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您可能想查看PhantomReference

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

    【讨论】:

    • 是的,幻影引用似乎是我所追求的,我可以在 GC 的工作流程中“挂钩”并干预某些对象。然而,实现它很可能比手动管理它们更复杂,更不确定,我想我会卷起袖子去做!
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 实际上关闭事件对临时文件是免费的... File.deleteOnExit 就是这样做的,没有任何额外的代码...问题是应用程序没有退出!至少在这段代码可能产生影响的地方不是。这只是让我不时进行批量擦除。
    【解决方案4】:

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

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

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

    2. 您应该使用 DeleteOnExit。

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

    【讨论】:

    • 1 - finalize 必须在 GC 将声明的类上有用,因此在这种情况下,我将不得不从 Java 覆盖 File 类,我不愿意这样做。 2-我明确表示deleteOnExit不会这样做,该程序理论上不会退出......曾经3-是的......基本上回到创建我自己的临时文件处理......我教过GC,因为要求这些资源是很自然的,我认为这不是那么简单。
    【解决方案5】:

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

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

    如果 Java 以大堆大小启动,这两种情况都特别频繁地发生 - 这在服务器端并不罕见。

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

    【讨论】:

      【解决方案6】:

      你可以为一个文件创建一个包装器,当对象被垃圾回收时,它使用finalizer 来删除你的文件。

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

      【讨论】:

      • 是的,但我需要扩展 File 类 + 因为你和其他人都说不是非常可靠。
      【解决方案7】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-30
        • 1970-01-01
        • 1970-01-01
        • 2019-08-05
        • 1970-01-01
        • 2013-01-26
        • 2011-07-24
        • 2012-03-24
        相关资源
        最近更新 更多