web-dev-qa-db-ja.com

JVMフルGCが世界を止める必要があるのはなぜですか?

私はこの質問を受け、「JVMはオブジェクトを移動する必要があるため」と答えましたが、後でGoogleで検索して、妥当な答えが見つからなかったようです。

50
cedrics

まず、 wikipediaのガベージコレクションの記事 は本当に良い読書です。

といえば。

一般に、GCはStop-the-Worldポーズを必要としません。 (ほぼ)一時停止のないJVM実装があります(例: Azul Zing JVM )。 JVMがSTWでガベージを収集する必要がある場合は常に、使用しているアルゴリズムに依存します。

Mark Sweep Compact(MSC)は、デフォルトでHotSpotで使用される一般的なアルゴリズムです。 STW方式で実装され、3つのフェーズがあります。

  • MARK-ライブオブジェクトグラフを走査して、到達可能なオブジェクトをマークします
  • SWEEP-メモリをスキャンしてマークされていないメモリを見つける
  • COMPACT-マークされたオブジェクトを再配置して空きメモリを最適化する

ヒープ内のオブジェクトを再配置する場合、JVMはこのオブジェクトへのすべての参照を修正する必要があります。再配置プロセス中、オブジェクトグラフは一貫性がないため、STWの一時停止が必要です。

Concurrent Mark Sweep(CMS)は、HotSpot JVMの別のアルゴリズムで、古いスペースコレクション(完全なコレクションとまったく同じではない)でSTWポーズを使用しません。

CMSは、書き込みバリア(Javaヒープ)で参照を書き込むたびにトリガーするトリガー)を使用して、MARKの同時バージョンを実装し、COMPACTを使用しません。これらの場合、CMSはSTW mark-sweep-compactコレクションにフォールバックします。

G1もあります。これは、MSCの増分バリエーションです。私のブログで HotSpot JVMのGCアルゴリズム について詳しく読むことができます。

66
Alexey Ragozin

JVMは、スループットGCを使用して、可能な限り多くの空きメモリを確保するためにSTWポーズが必要です。最も効果的であるのは、このような一時停止を使用することだけです。

低休止コレクター(CMS)を使用すると、アプリケーションを一時停止することなく、古い世代を同時にクリーンアップできます。欠点は、古い世代が断片化することです。断片化が進みすぎて圧縮が必要な場合、フルGC(STW)が発生します。ただし、フルGCを取得しないように、いつでもアプリケーションを調整できます。

G1 GCは特別な場合です。現在の主な目標は、(CMSのように)並行性を維持しながら、ヒープの断片化を少なくすることです。この目標を達成できない場合、JVMはSTWポーズに戻り、ヒープが完全にクリーン化および圧縮されます。

9
Pierre Laporte

stop-the-worldは、コレクターの実行中に新しいオブジェクトが割り当てられず、オブジェクトが突然到達不能になることを保証します。

利点は、増分ガベージコレクションよりも実装が簡単であり、高速であるということです。

0
Ludwig Wensauer

一時停止を最小限に抑えるほとんどのスキームであっても、ほとんどすべてのガベージコレクションスキームでスタック上の参照をスキャンするには、短い世界停止フェーズが必要です。 この回答 の詳細な説明。増分および同時アルゴリズムは、これらの一時停止を最小限に抑えるために一生懸命に働きますが、ほとんどの場合はそれを維持します。

実際には、オブジェクトを移動しながら世界を止める必要のない移動/圧縮メソッドもあります(スタッカートが思い浮かびます)

0
textshell