2012-07-20 50 views
11

我的Java應用程序(這是相當多的代碼)執行大量文件操作。在我的應用程序中,我需要將文件從一個位置移動到另一個位置,爲此,我使用JDK7中的Files.move方法。強制Java發佈Java中的所有文件鎖/句柄

當我嘗試這樣做時,出現一個錯誤,告訴我該文件正在使用中。我知道這是我的代碼鎖定這個資源的一部分。

如何強制我的Java應用程序在調用移動/重命名我的文件的函數之前釋放所有鎖?

如果這是不可能的,有沒有簡單的方法來檢查我的代碼的哪一部分鎖定文件?考慮到代碼的數量,通過我的整個代碼庫尋找未關閉的文件句柄將是一場噩夢。

感謝

+0

也許的幫助:http://stackoverflow.com/questions/4179145/release-java-file-lock-in-windows – Chris 2013-02-17 11:50:41

回答

3

有了一個調試器,你可以看到在內存中你有對象的所有實例的幫助(在Netbeans的,這將是視窗|調試|裝入的類,然後右鍵 - >顯示實例)。然後,您可以看到您擁有的所有實例,並確定那些指向您嘗試移動的文件的實例。一旦你找到了你的文件的引用,你可以看到誰仍然持有引用。

如果沒有人持有對該文件的引用,那麼可能在不調用close()的情況下放棄該實例,並且該文件通常只會在垃圾回收後纔會被釋放。這使得以前的方法無用,因爲我認爲調試器會自動爲您收集這些流。也許你可以在流構造函數中放置一個條件斷點,並且只在構造函數參數指向你的文件時才告訴它停止。

如果您找不到任何東西,作爲最後一招,您可以嘗試在移動操作之前放幾個System.gc()來電,並查看您是否有任何改進。很明顯,這只是一個快速修復的問題,給你一些時間,直到你找到真正的問題。

+0

實際上'文件'實例不鎖定文件。 「文件」只是文件或目錄路徑名稱的表示。 'System.gc()'不會關閉任何打開的文件流。 – 2012-07-20 15:09:07

+0

你對「文件」說得對。我更正了答案以引用'FileInputStream' /'FileOutputStream'。不過,我維持關於'System.gc()'的建議:兩個類都有一個關閉流的'finalize'方法,所以如果你只是在不調用close的情況下丟棄對象,垃圾收集可能會有所幫助。 – Flavio 2012-07-23 07:32:35

+0

你對文件流中的finalize()是正確的,所以,你是對的,它可以提供幫助。雖然它很脆弱!你無法控制什麼時候垃圾收集發生,也不能收集什麼,所以你不想在生產中依賴這種行爲。 – 2012-07-23 17:15:17

3

除了正確關閉流(最好在try.. finally塊內)之外,任何解決方案都將是一件麻煩的工作,並且會使事情變得比以前更加不穩定。

我知道在一個龐大的代碼庫中解決這個問題是一種痛苦。如果你不想跋涉你的代碼,FindBugs擅長定位未封閉的流。有一個Eclipse插件,你可以將它發現的錯誤過濾到你感興趣的那些。

3

File()對象沒有鎖定一個文件,但FileStream(FileInputStream/FileOutputStream)鎖定它。所以你必須爲Streams寫一個HelperClass(例如Singleton),記錄所有的Streams。

但請注意,如果您在代碼中存在泄漏,修復錯誤比關閉所有文件要好得多。