16bit!

エンジニアじゃなくなっちゃった人が何かを書くブログ

【Java】GCとfinalizeメソッドの関係

ガベージ・コレクションとfinalizerメソッドの関係について、ちょこっと調べたので簡単にメモしておく。


1.finalizeメソッドとFinalizer
 Finalizer・・・オブジェクトのfinalizeメソッドを呼び出すためのスレッド。


2.finalizeメソッドの有無によるGCの挙動の違い
 2-1.finalizeメソッドがない時

引用:@IT

 finalizeメソッドがない場合、オブジェクトはルートセットから参照されなくなった時点でGC対象となり、
 次のGC実行時に破棄される。


 2-2.finalizeメソッドがある時

引用:@IT

 finlaizeメソッドがある場合、オブジェクトはルートセットから参照されなくなった時点でGC対象となり、
 次のGC実行時に、GCによってfinalize対象リストへと登録される
 そして、Finalizerスレッドがfinalizeメソッドを実行した時点で、再度GC対象となり、
 次のGC実行時に、今度こそ本当に破棄される。
 つまり、finalizeが定義されているオブジェクトが破棄されるまでには、少なくとも2回以上のGCが走る必要がある

 また、当然ながらfinalizeが定義されているオブジェクトだけでなく、
 そのインスタンスが参照するオブジェクトもまた初回のGCでは解放されない。

 さらに、finalizeメソッドが実行される順番は不定であり、
 期待通りのタイミングでfinalizeメソッドが呼ばれるとは限らない。
 特にオブジェクトを大量に生成した場合には、Finalizerスレッドが処理に追いつかず、
 2回目のGC時にもまだFinalizerからの参照が残っているために、オブジェクトが破棄されない可能性がある。


3.finalizeメソッドは実行されないことがある
 上記2-2.で記載した通り、finalizeメソッドはGCによりfinalize対象リストに
 登録されたオブジェクトに対して行われるものなので、
 GCが実行されない限りfinalizeは呼ばれない。
 そして、アプリケーション(javaコマンド)が終了する際にはGCは呼ばれない(?)ことがあるようなので、
 finalizeメソッドは実行されないままアプリケーションが終了することがある



以上のことから、finalizeを実装したクラスを作成することには、

・意図したタイミングで破棄されないことによるOutOfMemoryのリスク
・finalizeが走らないことによるメモリリークの可能性

等のリスクがあるため、可能な限りfinalizeメソッドは実装しない方が良いと思われる。


<参考>
 JavaのGC頻度に惑わされた年末年始の苦いメモリ (3/3) - @IT
 3.10.5 java.lang.Object.finalize()についての注意事項
 Objectクラス finalizeメソッド