2010年5月13日木曜日

Effective javaまとめ6 ファイナライザを避ける1

忙しいほど覚醒するパターン

---------------------------------------------------
■項目6 ファイナライザを避ける

ファイナライザには有効な使用方法が多少ありますが、基本的には使用することを避けるべきです。

ファイナライザはC++のデストラクタと違い、呼び出されるタイミングを予測することができません。

デストラクタは、オブジェクトに関連付けられているメモリ領域を回収する通常の方法として利用されます。
javaではオブジェクトが到達不可能な状態になると、ガーベージコレクタにより自動的に関連付けられているメモリ領域が回収されます。

デストラクタは、メモリ以外の資源を回収するためにも使用されます。
javaでは、それらの目的で、try finally ブロックを利用します。

オブイェクトが到達不可能な状態になってからファイナライザがjvmによって実行させるまでの時間は、どれだけの長さにもなりえます。jvm実装ごとに大きく異なっています。
これは、時間的な制約のある事象をファイナライザで行うべきではないことを示してます。

クラスにファイナライザを提供することで、そこクラスのインスタンスの回収が遅れる可能性もあります。
ファイナライザを実行するためのスレッドが、そのアプリケーションの他のスレッドより低い優先順位で動作している場合、オブジェクトがファイナライズ対象となる速さが、オブジェクトがファイナライズされる速度を上回る可能性があります。そうすると、どんどん回収されないメモリ領域が増えていき、最終的にアウトオブメモリーとなる可能性があります。

さらに、ファイナライザは必ず実行されるとは限りません。(javaの言語仕様では、ファイナライザの実行を保証していないためです)結果として、ファイナライザで重要な永続性のある状態を更新するような処理をお行うことは望ましくない、と言えます。

System.gc()やSystem,runFinalizer()は、ファイナライザが実行される可能性を高めるものではありませうが、実行されることを保証するものではありません。System.runFinalizersOnExit()とRuntime.runFinalizeOnExit()は、ファイナライズを保証するらしいです。ただ、致命的な欠陥があるようで、推奨されていません。(どんな欠陥かはなんとなくしか調べなかったので記載しません)

---> 続く

0 件のコメント:

コメントを投稿