文件删除方法File.delete()返回false。

3
我已经使用Java编程创建了一个文件,并使用Apache Commons Logging API,特别是Log4j实现记录了一些数据。
在完成日志记录后,我将Log类的引用设置为null。当我尝试删除我一直在记录日志的文件时,File.delete()返回false。
在调试期间从Windows资源管理器中删除该文件(即在调用File.delete()之前),我会收到“无法删除:正在被另一个程序使用”的通知。
我的代码中没有打开该文件的依赖项(所有流都已关闭)。唯一可能访问该文件的对象是Log对象,在调用File.delete()之前我已将其设置为null。
有没有办法查看哪个具体对象持有对文件资源的引用? 除了将其设置为null之外,是否有其他方法来强制释放Log对象的资源? 我能否强制删除该文件?
2个回答

5
只将变量设置为null并不会强制回收对象。此外,它有可能被注册在某种静态映射中 - 你需要检查实现以确保。(我认为某些版本使用了弱引用,但其他版本则没有。)
你是否有必要立即删除文件?你可以尝试使用File.deleteOnExit(),它可能有更好的删除文件的机会 - 尽管这取决于时间安排的具体情况。(另外,请注意如果你重复调用deleteOnExit可能会导致内存泄漏。)
你能否在应用程序完成后或者下一次启动时删除该文件?
或者,你可以使用一个日志实现来滚动文件 - 尝试强制执行滚动,然后删除旧文件?

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

3

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


更新:

问题在于log4js的appender对您的文件有写锁。因此,在appender未关闭时,您无法删除该文件。解决方案是生成较小的文件,或将附加标志设置为false,以便在重新启动服务器时自动删除旧的日志文件。

尝试使用

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

关闭操作确保所有正在使用日志文件的进程都被终止,从而解决问题。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接