Java と手動でのファイナライズの実行
-
09-06-2019 - |
質問
電話したら finalize()
私のプログラムコードのオブジェクトでは、 JVM ガベージ コレクターがこのオブジェクトを処理するときにメソッドを再度実行しますか?
これはおおよその例です。
MyObject m = new MyObject();
m.finalize();
m = null;
System.gc()
明示的に呼び出しますか? finalize()
を作る JVMのガベージ コレクターを実行しないようにする finalize()
オブジェクトのメソッド m
?
解決
この単純なテスト プログラムによると、JVM は明示的に Finalize() を呼び出した場合でも呼び出しを行います。
private static class Blah
{
public void finalize() { System.out.println("finalizing!"); }
}
private static void f() throws Throwable
{
Blah blah = new Blah();
blah.finalize();
}
public static void main(String[] args) throws Throwable
{
System.out.println("start");
f();
System.gc();
System.out.println("done");
}
出力は次のとおりです。
始める
仕上げ中!
仕上げ中!
終わり
世の中のすべてのリソースは、finalize() を明示的に呼び出さないように指示しており、呼び出されるかどうか、いつ呼び出されるかについての保証がないため、メソッドを実装することさえほとんどありません。すべてのリソースを手動で閉じた方がよいでしょう。
他のヒント
ファイナライズの機能を理解するには、ガベージ コレクター (GC) ワークフローを理解する必要があります。.finalize() を呼び出しても、ガベージ コレクターは呼び出されず、system.gc も呼び出されません。実際、コーダにとってファイナライズが役立つのは、オブジェクトの参照を「参照されていない」と宣言することです。
GC は JVM の実行操作を強制的に一時停止するため、パフォーマンスが低下します。操作中、GC はルート オブジェクト (メイン メソッド呼び出し) から開始して、参照されているすべてのオブジェクトを走査します。この中断時間は、オブジェクトを参照されていないと手動で宣言することで短縮できます。これは、自動実行によってオブジェクト参照が廃止されたと宣言するための操作コストが削減されるためです。Finalize() を宣言することにより、コーダーはオブジェクトへの参照を古いものに設定します。そのため、GC 操作の次回の実行時に、GC 実行は操作時間を使用せずにオブジェクトをスイープします。
引用:「オブジェクトに対して Finalize メソッドが呼び出された後は、まだ終了していないスレッドからこのオブジェクトにアクセスできる手段がなくなったと Java 仮想マシンが再度判断するまで、それ以上のアクションは実行されません。完了する準備ができている他のオブジェクトまたはクラスによるアクション。その時点でオブジェクトは破棄される可能性があります。" java.Object.finalize(); に関する Java API ドキュメントより
詳細な説明については、以下も確認できます。 javabook.コンピュータウェア
Finalize メソッドは、特定のオブジェクトに対して JVM によって複数回呼び出されることはありません。いずれにせよ、finalize が呼び出されるという保証はないので、それに依存すべきではありません。クリーンアップコードを実行する必要があるためにfinalizeを呼び出している場合は、それを別のメソッドに入れて明示的にすることをお勧めします。
public void cleanUp() {
.
.
.
}
myInstance.cleanUp();