我的Java应用程序(这是相当多的代码)执行了大量的文件操作。在我的应用程序的某一点上,我需要将文件从一个位置移动到另一个位置,为此我正在使用 Files.move
JDK7的方法。
当我尝试这样做时,我收到一个错误,告诉我该文件正在使用中。我知道一个事实是我的代码的一部分是锁定这个资源。
在调用移动/重命名文件的函数之前,如何强制我的Java应用程序释放所有锁?
如果这是不可能的,有没有一种简单的方法来检查我的代码的哪一部分锁定文件?考虑到代码的数量,在整个代码库中跋涉以找到未封闭的文件句柄将是一场噩梦。
谢谢
File()对象不会锁定文件,但FileStream(FileInputStream / FileOutputStream)会锁定它。因此,您必须为Streams编写一个HelperClass(例如Singleton),并记录所有Streams。
但请注意,如果您的代码中有泄漏,修复错误要比关闭所有文件要好得多。
在调试器的帮助下,您可以看到内存中对象的所有实例(在Netbeans中,这将是Windows | Debugging | Loaded Classes,然后右键单击 - > Show instances)。然后你可以看到所有的 FileInputStream
/FileOutputStream
您拥有的实例,并标识那些指向您要移动的文件的实例。找到对文件的引用后,您可以看到谁仍在保留引用。
如果没有人持有对该文件的引用,则可能在没有调用的情况下丢弃该实例 close()
,并且文件通常只在垃圾收集后释放。这使得以前的方法无用,因为我认为调试器会自动为您垃圾收集这些流。也许你可以在流构造函数中放置一个条件断点,并告诉它只在构造函数参数引用你的文件时停止。
如果你找不到任何东西,作为最后的手段你可以尝试放几个 System.gc()
在移动操作之前调用,看看你是否有任何改进。显然,这只是快速和肮脏的修复,给你一些时间,直到你找到实际的问题。
除了正确关闭流之外的任何解决方案(最好是在 try.. finally
块)将是一个拙劣的工作,并将冒险使事情比现有的更不稳定。
我知道在大型代码库中解决这个问题很痛苦。如果你不想跋涉你的代码, FindBugs的 擅长定位未封闭的溪流。有一个Eclipse插件,您可以将它找到的错误过滤到您感兴趣的那些。