2

私の理解では、 finalize() と GC は 2 つの異なる側面です。GC は finalize() メソッドを使用してオブジェクトのメモリを解放します。System.gc() を明示的に呼び出したとしても、GC がいつ発生するかはわかりません。しかし、オブジェクトに対して明示的に finalize() を呼び出すことができます。

Will the function be executed immediately(memory freed) or it waits till GC
occurs like System.gc() call?

また、ドキュメントによると、特定のオブジェクトに対して Java 仮想マシンによって finalize メソッドが複数回呼び出されることはありません。

それでは、最初に finalize() を呼び出して、後で GC を実行するとどうなるでしょうか。

If object memory is not freed on explicit call to object.finalize() then would't 
it being called again in the GC process violate the calling only once rule? 
4

3 に答える 3

7

あなたはそれを完全に間違っています。

簡単な答え: finalize()オブジェクトがガベージ コレクションの準備が整う直前に (開いているファイルなどの) リソースをクリーンアップする手段です (オブジェクトへの強い参照がない場合)。呼び出される場合と呼び出されない場合があります。これは、メモリ解放の一歩先を行っています。

長い答え:

finalize() メソッドの呼び出しを担当するファイナライザー スレッドと呼ばれる別のデーモン スレッドがあります。ファイナライズ キューは、finalize() メソッドを呼び出す準備が整ったオブジェクトが配置されるキューです。

  1. オブジェクトが作成されると、JVM はユーザーが finalize() メソッドをオーバーライドしたかどうかをチェックします。ある場合、この特定のオブジェクトには finalize() メソッドがあることが内部的に記録されます。

オブジェクトがガベージ コレクションの準備ができると、ガベージ コレクタ スレッドは、この特定のオブジェクトに (1) で説明したテーブルからの finalize() があるかどうかをチェックします。

  • 2a) そうでない場合は、ガベージ コレクションに送信されます。

    2b) 持っている場合は、ファイナライズ キューに追加されます。そして、テーブルからオブジェクトのエントリを削除します (1)。

ファイナライザー スレッドはキューをポーリングし続けます。キュー内のすべてのオブジェクトに対して、その finalize() メソッドが呼び出されます。(2) からの finalize() サイクルを呼び出した後、再び繰り返されます。このオブジェクトがまだ強い参照を持っていない場合は、GC に送信されます。存在する場合は、(2b) でエントリが削除されたため、ALWAYS (2a) が呼び出されます。

Basically finalize() method is only called once.

では、上記のサイクルの問題は何でしょうか?

(1)より。オブジェクトの作成に余分な時間がかかります。Javaでのメモリ割り当ては、malloc/callocなどよりも5倍から10倍高速です。得られた時間は、テーブル内のオブジェクトに注意するなどの手順ですべて失われます。私は一度試しました。ループ内に 100000 個のオブジェクトを作成し、2 つのケースでプログラムが終了するまでの時間を測定します。20% 高速であることがわかりました。

(2b) から: メモリ リークと飢餓。キュー内のオブジェクトが多くのメモリ リソースへの参照を持っている場合、このオブジェクトが GC の準備ができていない限り、それらのオブジェクトはすべて解放されません。すべてのオブジェクトが重いオブジェクトである場合は、不足する可能性があります。

(2b) より: finalize() は 1 回だけ呼び出されるため、finalize() で「この」オブジェクトへの強い参照があった場合はどうなるでしょうか。次にオブジェクトの finalie() が呼び出されないため、オブジェクトが一貫性のない状態のままになる可能性があります。

finalize() 内で例外がスローされた場合、それは無視されます。

GC がいつ呼び出されるかを制御できないため、 finalize() がいつ呼び出されるかはわかりません。finalize() の値を出力しているのに、finalize() が呼び出されるまでにプログラムが終了している可能性があるため、出力が表示されないことがあります。

したがって、使用は避けてください。代わりに、必要なリソースや最終ログなどを閉じるメソッド dispose() を作成します。

于 2013-08-29T12:11:30.727 に答える
1

ドキュメントに従って:

finalize メソッドは、任意のオブジェクトに対して Java 仮想マシンによって 2 回以上呼び出されることはありません。

ただし、GC を強制的に実行することはできませんSystem.gc()finalize()したがって、最善のアプローチは、オーバーライド時にリソースを解放するコードをメソッドに入れることです。

于 2013-08-29T12:12:02.373 に答える
1

答えは Object.finalize API にあります

1) GC は finalize() を呼び出すため、finalize() と GC は 2 つの異なる側面ではありません

2) finalize を手動で呼び出すべきではありませんが、そうしてもメモリは解放されず、GC の動作には影響しません。

3) GC が finalize を 2 回呼び出さないことが保証されていると言われています。呼び出しはカウントされません。

于 2013-08-29T12:15:40.640 に答える