14

我的 Java 应用程序(相当多的代码)执行大量文件操作。在我的应用程序中,我需要将文件从一个位置移动到另一个位置,为此我使用Files.moveJDK7 中的方法。

当我尝试执行此操作时,我收到一条错误消息,告诉我该文件正在使用中。我知道这是我的代码的一部分锁定了这个资源。

在调用移动/重命名文件的函数之前,如何强制我的 Java 应用程序释放所有锁?

如果这是不可能的,是否有一种简单的方法来检查我的代码的哪一部分正在锁定文件?考虑到代码量,在我的整个代码库中寻找未关闭的文件句柄将是一场噩梦。

谢谢

4

3 回答 3

4

在调试器的帮助下,您可以查看内存中的所有对象实例(在 Netbeans 中,这将是 Windows | Debugging | Loaded Classes,然后右键单击 -> Show instances)。然后,您可以查看您拥有的所有FileInputStream/FileOutputStream实例,并识别那些指向您尝试移动的文件的实例。找到对文件的引用后,您可以看到谁仍然持有该引用。

如果没有人持有对该文件的引用,则该实例可能在没有调用的情况下被丢弃close(),并且该文件通常只有在垃圾回收后才会被释放。这使得以前的方法毫无用处,因为我认为调试器会自动为您收集这些流。也许您可以在流构造函数中放置一个条件断点,并告诉它仅在构造函数参数引用您的文件时才停止。

如果您找不到任何东西,作为最后的手段,您可以尝试System.gc()在移动操作之前拨打几个电话,看看您是否有任何改进。显然,这只是快速而肮脏的修复,给您一些时间,直到您找到实际问题。

于 2012-07-20T14:09:50.270 回答
4

除了正确关闭流(最好在一个块内)之外的任何解决方案try.. finally都将是一项糟糕的工作,并且有可能使事情变得比现在更不稳定。

我知道在大型代码库中解决这个问题很痛苦。如果您不想在代码中费力,FindBugs擅长定位未关闭的流。有一个 Eclipse 插件,您可以将它发现的错误过滤给您感兴趣的人。

于 2012-07-20T14:52:02.053 回答
4

File() 对象不会锁定文件,但 FileStream (FileInputStream/FileOutputStream) 会锁定它。因此,您必须为您的 Streams 编写一个 HelperClass(例如 Singleton),以记录所有 Streams。

但是请注意,如果您的代码中有泄漏,修复错误比硬关闭所有文件要好得多。

于 2012-07-23T08:09:44.713 回答