问题 强制java释放Java中的所有文件锁/句柄


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

当我尝试这样做时,我收到一个错误,告诉我该文件正在使用中。我知道一个事实是我的代码的一部分是锁定这个资源。

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

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

谢谢


1730
2017-07-20 12:50


起源

也许是帮助: stackoverflow.com/questions/4179145/... - Chris


答案:


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

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


4
2017-07-23 08:09





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

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

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


3
2017-07-20 14:09



其实 File 实例不保存文件锁。一个 File 只是文件或目录路径名的表示。 System.gc() 从不关闭任何打开的文件流。 - ᴇʟᴇvᴀтᴇ
你是对的 File。我纠正了答案 FileInputStream/FileOutputStream。不过,我保留了我的建议 System.gc():这两个班有一个 finalize 关闭流的方法,所以如果你只是丢弃了对象而没有调用close,垃圾收集可能有所帮助。 - Flavio
你对文件流中的finalize()是正确的,所以,你说得对,它可以提供帮助。虽然它很脆弱!您无法控制垃圾收集何时发生以及收集的内容,因此您不希望在生产中依赖此类行为。 - ᴇʟᴇvᴀтᴇ


除了正确关闭流之外的任何解决方案(最好是在 try.. finally 块)将是一个拙劣的工作,并将冒险使事情比现有的更不稳定。

我知道在大型代码库中解决这个问题很痛苦。如果你不想跋涉你的代码, FindBugs的 擅长定位未封闭的溪流。有一个Eclipse插件,您可以将它找到的错误过滤到您感兴趣的那些。


3
2017-07-20 14:52