5

System.gc()またはfinalize()メソッドが呼び出されたときに内部(JVM)で何が起こりましたか?

これは本当にゴミを収集するのですか、それともパフォーマンスを低下させるのですか?

4

6 に答える 6

8

System.gc()を呼び出したときに何が起こるかは、JVM に依存します。JVM はこの呼び出しを、ガベージコレクターを実行するのに適した時期である可能性があると見なすので、それに依存しないでください。

オブジェクトのfinalize()メソッドは、JVM がそのオブジェクトへの到達可能な参照がないと判断したときに、ガベージ コレクターによってそのオブジェクトに対して実行されます。コード内で呼び出すべきではありません。finalize() は、プログラムが最終参照を失った時点では呼び出されませんが、ガベージ コレクターが実行される将来の時点で呼び出されることに注意してください。そのため、特定の時点 (または全て)。

于 2009-05-21T13:51:36.217 に答える
3

ガベージ コレクションの内部を知りたい場合は、Sun のHotspot Memory Management Whitepaperをお読みください。

于 2009-05-21T12:32:27.143 に答える
1

System.gc()名前が示すように、ガベージ コレクターを呼び出すことによって実行されます。この時点で、オブジェクトが実際に削除さfinalize()れると、これらのオブジェクトが消える前に が呼び出されます。

最後の質問には " or" を含めないでください。ガベージ コレクションパフォーマンスの低下です。

gcそれはあなたにとって本当に良い仕事をするので、通常はまったく気にするべきではありません. 特定の時点で多くのオブジェクトを削除したい使用シナリオがあります。それなら実現可能です。

于 2009-05-21T12:24:21.387 に答える
0

System.gc() はメモリをクリーンアップし、finalize() を使用して個々のオブジェクトを取り除きます。

于 2012-04-17T07:01:18.723 に答える
0

finalize() は、オブジェクトがガベージ コレクションの準備が整う直前 (オブジェクトに強い参照がない場合) に、コードの最後のビットを実行する手段です。

では、いつ使用する必要がありますか?現在の 2 つの場合のみ:

  1. 一部のサービスが閉鎖されていること、または必要な最終的な変更が行われていることを確認するための安全として。たとえば、InputStream クラスはこれを使用して I/O ストリームを閉じます。たとえば、BufferedInputStream のインスタンスを作成したとします。それを使用した後、手動で close() することを想定しています。しかし、それを忘れる可能性があるため、finalize() はストリームを close() するためのセーフティ ネットとして機能します。
  2. ネイティブの使用中。ガベージ コレクターはネイティブ オブジェクトを制御できないため、finalize() を使用してそれを再利用できます。

上記の 2 つのケース以外では、決して使用しないでください。理由を理解するには?オブジェクトの機能とライフサイクルを理解する必要があります。

はじめに: 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() というメソッドを作成して、必要なリソースを閉じるか、最終的なログなど のために完全な投稿を行います。これがクリアされることを願っています。

于 2011-10-18T08:40:05.830 に答える