blog

JavaJavaのfinalize()メソッド

Javaのゴミコレクタは、newによって生成されたメモリブロックのみを解放し、newによって生成されなかった「特殊メモリ」は管理しません。 いわゆる特殊メモリとは、C/C++を使ってJNI経由でシステ...

Sep 13, 2020 · 2 min. read
シェア

Javaでは、finalizeは次のように動作すると仮定しています。ゴミ収集機がメモリーを回収し、オブジェクトが占有しているメモリーを解放する準備ができたら、まずそのオブジェクトのfinalizeメソッドを呼び出し、次にそのオブジェクトをゴミとして回収する必要があるときだけ、実際にオブジェクトを回収します!

finalizeメソッドの役割:日々の開発でfinalizeメソッドを呼び出す必要はありませんし、推奨もされません。JVMが管理するメモリはGCに任されています。finalizeの目的は、主にいくつかの特別なメモリのために使用されます:特別なメモリのアプリケーションでのJNIコールの使用など。finalizeは、すべてのオブジェクトのメモリが解放された後にGCが発生することを確認するために、次のGCが発生したときに、特別なメモリのアプリケーションでJNIコールを再要求する呼び出しの前にGCで使用されます。

ゴミの収集

  • Javaのゴミコレクターは、newによって作成されたメモリブロックのみを解放し、newによって作成されなかった「特別なメモリ」は管理しません。
  • いわゆる特殊メモリとは、JNIを介してC/C++でシステムから要求されるメモリのことで、手動でクリアしなければメモリに占有されたままになります。
  • また、ゴミの収集にはそれ自身のオーバーヘッドがあるので、VMはあまり頻繁にGCしませんし、JVMはメモリがなくなりそうになったときだけGCをトリガーします。

finalize()

  • 以上から、Javaのオブジェクトは必ずしもすべてゴミになるわけではなく、オブジェクトが不要になった場合、手動でそれらの「特別なメモリ」を処理する必要がありますが、Javaにはデストラクタがないため、finalize()メソッドを提供してクリーンアップ作業を行うことができます。
  • システムがGCを実行する場合、まずfinalizeメソッドを呼び出し、次にオブジェクトのメモリーを回収します。ネイティブで要求されたメモリをGCが再利用する方法はないため、finalizeはゴミ収集の前に重要なクリーンアップを行うために使用されます。
  • そのため、finalizeは一般的にJNIが使用されるシナリオで使用され、特別なメモリを解放するためにfinalizeでネイティブメソッドを呼び出す必要があります!
  • GCが起こらなければ、finalizeも起こりません。finalizeはObjectのプロテクト・メソッドで、クラス・ファミリーの外からはアクセスできません。

デストラクタの比較対照

  • まず第一に、これはデストラクタではありません。JavaにはGCメカニズムがあるため、デストラクタという概念がありません!
  • デストラクタは間違いなくオブジェクトを破壊しますが、finalizeはgcメカニズムが頻繁に起こるわけではないので、不確定に実行されます。

その他

  • System.gc()を呼び出すと、finalizeメソッドを起動するためにgcが強制的に起こります!しかし、GCはゴミのようなオブジェクトだけをGCし、ゴミでないオブジェクトにはfinalizeは呼ばれません。プログラムの終了とGCは同じ概念ではありません。
  • 通常、finalize()はすべて直接呼び出しますが、super.finalize()は親クラスを使うだけです。
  • finalizeは通常使われません!実行されるかどうかの不確実性が大きすぎるからです。finalizeを使用してオブジェクトを取り戻すことを期待しないでください。finalizeは、システムがGCを行うときに特別なメモリをクリーンアップするだけで、あなたのコントロールの範囲外です!
Read next

比較プログラミング

ソースコードの前に秘密はない」ということわざは、部分的にしか真実ではありません。目の前に偉大な文学作品があるようなもので、すべての単語を読むことができても、その機微を見抜くことはできないかもしれません。そのためには通常、優れた読者であるか、優れた作家である必要があります。プログラマーとして、ソースコードに含まれる秘密を察知する能力は、プログラミングの能力、プロジェクトの背景に関する知識......に依存します。

Sep 13, 2020 · 2 min read