【问题标题】:File.delete() returns falseFile.delete() 返回 false
【发布时间】:2011-07-21 01:57:30
【问题描述】:

我从我的 java 编程中创建了一个文件,并且正在使用 Apache Commons Logging API 记录一些数据,特别是 Log4j 实现。

日志记录完成后,我将对 Log 类的引用设置为 null。当我现在尝试删除我一直在记录的文件时,File.delete() 返回 false。

在调试期间(在调用 File.delete() 之前)从 Windows 资源管理器中删除文件时,我收到“无法删除:正在被另一个程序使用”的通知。

我的代码中的文件没有打开的依赖项(所有流都已关闭)。唯一可以访问该文件的对象是 Log 对象,我在调用 File.delete() 之前将其设置为 null

无论如何我可以看到哪个特定对象持有对文件资源的引用? 除了将其设置为 null 之外,还有其他方法可以强制 Log 对象释放资源吗? 我可以强制删除文件吗?

【问题讨论】:

    标签: java logging file-io log4j apache-commons-logging


    【解决方案1】:

    仅将变量设置为 null 不会强制对对象进行垃圾回收。此外,它有可能在某种静态地图中注册 - 您必须检查实现以确定。 (我认为有些版本使用弱引用,但其他版本没有。)

    你有什么理由删除文件吗?您可能想尝试File.deleteOnExit(),这可能更有可能删除文件 - 尽管这取决于具体的时间安排。 (另外,如果您反复拨打deleteOnExit,请注意possible memory leak。)

    您能否在应用程序完成后删除该文件,或者可能在下次启动时删除该文件?

    或者,您可以使用滚动文件的日志实现 - 尝试强制滚动,然后删除旧文件?

    【讨论】:

    • 我正在编写一个将在代码存储库上自动执行的测试。我无法更改正在测试的代码的实现,因此无法从 Log4j 迁移。如何强制对已设置为 null 的对象进行垃圾回收?
    • @Shailesh:重要的是你明白你不能将 object 设置为 null,只能将 variable 设置为 null。如果该变量是唯一引用该对象的东西,那么它将有资格进行垃圾收集 - 但我怀疑您会发现 log4j 中隐藏了其他引用。如果这是一个测试,您可能想尝试将 log4j 配置为根本不使用文件进行日志记录 - 登录到 StringBuilder 或类似的东西会更好。
    • 谢谢,没想到 Log4j 设置了对对象的多个引用。登录到 StringBuilder 对我来说是最好的解决方法。
    【解决方案2】:

    在您的情况下,记录器正在将其写入文件 - 文件被另一个进程锁定。


    更新:

    问题是 log4js 的 appender 对你的文件有一个写锁。因此,虽然 appender 未关闭,但您无法删除该文件。一个解决方案是您生成较小的文件,或者将附加标志设置为 false,这样当您重新启动服务器时,旧的日志文件会自动删除。

    尝试使用

    org.apache.log4j.LogManager.shutdown();
    

    关闭确保所有正在使用日志文件的进程都已终止,这样可以解决问题。

    确保调用我们自己的 Appender 实现(它是 AppenderSkeleton 的子类)的 close() 方法,以便它正确地从 getAllAppenders() 关闭附加程序。

    【讨论】:

      猜你喜欢
      • 2021-06-10
      • 2013-02-26
      • 1970-01-01
      • 2010-11-02
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      相关资源
      最近更新 更多