web-dev-qa-db-ja.com

Javaですべてのファイルロック/ハンドルを解放するように強制するJava

私のJavaアプリケーション(かなりのコードです)は多くのファイル操作を行います。私のアプリケーションのある時点で、ファイルをある場所から別の場所に移動する必要があります。このために私はJDK7のFiles.moveメソッドを使用しています。

これを実行しようとすると、ファイルが使用中であることを示すエラーが表示されます。このリソースをロックしているのはコードの一部であることを私は知っています。

ファイルを移動/名前変更する関数を呼び出す前に、Javaアプリケーションにすべてのロックを解放させるにはどうすればよいですか?

これが不可能な場合、コードのどの部分がファイルをロックしているかを確認する簡単な方法はありますか?コードベース全体を調べて閉じられていないファイルハンドルを見つけることは、コードの量を考えると悪夢です。

ありがとう

13

File()オブジェクトはファイルをロックしませんが、FileStream(FileInputStream/FileOutputStream)はファイルをロックします。したがって、すべてのストリームをログに記録する、ストリームのHelperClass(Singletonなど)を作成する必要があります。

ただし、コードにリークがある場合は、すべてのファイルを完全に閉じるよりも、バグを修正する方がはるかに優れていることに注意してください。

4
Mirko

ストリームを適切に閉じる以外の解決策(できればtry.. finallyブロック内)は失敗の仕事になり、物事を以前よりも不安定にするリスクがあります。

大規模なコードベースでこれを修正するのは面倒だと思います。コードを調べたくない場合は、 FindBugs は閉じられていないストリームを見つけるのに適しています。 Eclipseプラグインがあり、見つけたバグを興味のあるものだけにフィルターすることができます。

3

デバッガの助けを借りて、メモリ内にあるオブジェクトのすべてのインスタンスを表示できます(Netbeansでは、これはWindows |デバッグ|ロードされたクラスになり、右クリック->インスタンスの表示になります)。次に、所有しているすべてのFileInputStream/FileOutputStreamインスタンスを確認し、移動しようとしているファイルを指しているインスタンスを特定できます。ファイルへの参照を見つけたら、誰がまだ参照を保持しているかを確認できます。

ファイルへの参照を保持している人がいない場合は、close()を呼び出さずにインスタンスが破棄された可能性があり、ファイルは通常、ガベージコレクションの後でのみ解放されます。デバッガーが自動的にそれらのストリームをガベージコレクションするので、これは前のアプローチを役に立たなくします。ストリームコンストラクター内に条件付きブレークポイントを設定し、コンストラクターパラメーターがファイルを参照している場合にのみ停止するように指示できるかもしれません。

何も見つからない場合は、最後の手段として、移動操作の前にSystem.gc()呼び出しをいくつか行って、改善があるかどうかを確認することができます。明らかに、これは、実際の問題が見つかるまでの時間を与えるための、手っ取り早い修正にすぎません。

3
Flavio