2012-05-01 6 views
0

Javaファイナライズに関するいくつかの質問があります。 たとえば、FileHelperクラスが1つあり、このクラスはファイルの読み取り、ファイルの書き込みなどに関連しています。 私はfinalize()メソッドをオーバーライドしてファイルを閉じるか、writeFile()メソッドの内部でファイルを閉じることができるかどうかをFileHelper class.NowのファイルwriteFile()で確認します。 自体?それは正しい方法ですか? File変数をメンバ変数として宣言しました。オーバーライドが悪い考えである場合、なぜfinalize()メソッドをオーバーライドしたいのですか?どのシナリオですか?私はファイルやフォントなどのシステムリソースを閉じることを言っている多くの記事を読んでいます。Javaファイナライズに関する疑問

答えて

3

可能な限り早くファイルを閉じることをお勧めします。あなたはFileHelperの静的メソッドを持っている場合は(あなたのヘルパーは、静的な「ヘルパー」メソッドの集まりであると仮定して)私が最優先のファイナライズの目的は、例えば、アンマネージリソースを解放している

static void writeFile(String fileName, String text) { // Exception 
// Open file here 
// write text 
// close it 
} 

内のファイルを閉じます誰かがそれを忘れた場合のためのファイル。 GCは、ファイルを実行したときの内側()誰かがあなたのヘルパーこのよう

FileHelper fileHelper = new FileHelper(file); 
fileHelper.writeFile(text); 
// forgot to fileHelper.close(); 

を使用して、ファイナライズを上書きし、Closeを呼び出している場合は閉じられます。問題:

  • 私は、以前のファイルはできるだけ早く閉じる必要があります言及したよう(ただし、早く;))GCが開始されますとき
  • それは決定不能だが(何体も知らない)
  • にのみ使用する必要があります呼び出し元がファイルを閉じるのを忘れる場合を避けるために。
+0

finalizeをオーバーライドすると、色の注釈を追加すると、GCがさらに高価になり(オブジェクトは少なくとも2回のGCパスを経て生き延びる)、JVMはメソッドを任意のタイムリーな方法で呼び出す義務はない - または全く。ファイナライズとGCについてはさまざまな記事がありますが、その方法をオーバーライドすることを強くお勧めします。 – yshavit

+0

もちろん、これはコーナーケースです。 I/Oを行うとGCのオーバーヘッドが心配されることはありません。私のローラーブレードとジェットを比較してみました。 –

+0

間違いなく、OPがnon-IOクラスでこのメソッドを使用することを検討していた場合には、私は精緻化していました。私が主題にいる間、私はそれを言いたいと思った。 – yshavit

0

finalize()を上書きするのは良い方法ではありません。私はコードでそれをやっただろう。

1

ファイナライザの使用はほとんどすべての状況で悪い考えです。 Java仕様によれば、ファイナライザが実行されることは保証されていません。たとえそれがあったとしても、いつ起こるかはあなたがコントロールできません。

ファイルを閉じるためのプライマリメカニズムとしてファイナライザを使用することは、常に悪い考えです。どうして? GCが長時間実行されないと、アプリケーションでファイル記述子が使い果たされ、ファイルオープンが失敗します。

開かれたストリームを処理する最も良い方法は、ローカル変数とパラメータにそれらを保持し、終了時に常に閉じていることを確認することです。try { ...} finallyを使用します。またはJava 7では、新しい「リソースを試してください」構文を使用します。

ストリームをメンバー変数に入れる必要がある場合は、ストリームを閉じるメソッドを親クラスに実装し、親クラスのインスタンスが閉じられることを確認する必要があります。


また、ストリーム「失われた」閉じるために、ファイナライザを使用して少しポイントがあることに留意すべきです。 が必要な外部リソースを使用するストリームクラスは、これを閉じるためのファイナライザを既に持っています。閉じるにはが必要です。

1

finalize()メソッドは、Javaガベージコレクタがオブジェクトを再利用しようとしているときにのみ呼び出されます。 finalizeメソッドでファイルハンドルを解放するのは悪い習慣です。

java.io.IOExceptionが発生する可能性があります。開いているファイルが多すぎると、ガベージコレクタがいつ実行されるかを保証できません。

もっと良いオプションは、finallyブロック内のファイルリーダー/ライターオブジェクトを閉じることです。実行が保証されているので。

finally { 
    // Always close input and output streams. Doing this closes 
    // the channels associated with them as well. 
    try { 
    if (fin != null) 
     fin.close(); 
    if (fout != null) 
     fout.close(); 
    } catch (IOException e) { 
    }} 

フィンとfoutはFileInputStreamオブジェクトとFileOutputStreamオブジェクトです。

関連する問題