2011-03-23 236 views
3

我已经从我的java编程创建了一个文件,并且正在记录某些数据使用Apache Commons Logging API,特别是Log4j实现。File.delete()返回false

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

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

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

有什么方法可以看到什么特定对象持有对文件资源的引用? 是否有任何其他方式强制Log对象释放资源,除了将其设置为null? 我可以强制删除文件吗?

回答

5

只需将该变量设置为null不会强制垃圾收集对象。另外,它有可能在某种静态地图中注册 - 您必须检查实施情况。 (我认为有些版本使用弱引用,但其他版本不使用。)

是不是有什么理由你删除文件吧?您可能想尝试File.deleteOnExit(),其中可能有更好的删除文件的机会 - 虽然它取决于具体的时间。 (此外,如果重复拨打deleteOnExit,请小心possible memory leak)。

您可以在应用程序完成后或者在下次启动后删除文件吗?

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

+0

我正在编写一个将在代码库中自动执行的测试。我无法更改我正在测试的代码的实现,所以无法从Log4j移动。我如何强制我设置为null的对象上的垃圾回收? – 2011-03-23 07:07:12

+0

@Shailesh:重要的是你明白你不能将* object *设置为null,只能设置一个* variable *。如果该变量是引用该对象的唯一东西,那么它将有资格进行垃圾回收 - 但我怀疑你会发现其他引用埋在log4j中。如果这是一个测试,你可能想尝试配置log4j不使用文件进行日志记录 - 登录到StringBuilder或类似的会更好。 – 2011-03-23 07:12:08

+0

谢谢,没有想到Log4j会设置多个对象的引用。记录到StringBuilder将是我最好的解决方法。 – 2011-03-23 07:16:10

3

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


更新:

的问题是,log4js'附加器对文件的写锁。所以,当appender没有关闭时,你不能删除文件。解决办法是生成较小的文件,或将append标志设置为false,因此当您重新启动服务器时,旧的日志文件会自动删除。

尝试使用

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

关闭确保正在使用的日志文件的所有进程都终止,这种方式解决了问题。

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