web-dev-qa-db-ja.com

Java GC:なぜ2つのサバイバー領域ですか?

Sun/OracleのJVMについては、GCアルゴリズムが新しい世代を1つのEdenリージョンと2つのサバイバーリージョンに分割することを読みました。私が疑問に思っているのは、なぜ1つだけではなく2つのサバイバー地域ですか?このアルゴリズムは、エデンと1つのサバイバーリージョン間(現在の2つのサバイバーリージョン間)でピンポンを続けることができます。または、このアプローチに欠点はありますか?

72
shrini1000

JRockitのGC実装は、エデンとサバイバーのスペースが1つだけで、あなたが提案するように機能すると思いますが、それについては引用しないでください。

HotSpot JVMの2つのサバイバースペースの理由は、断片化に対処する必要性を減らすためです。新しいオブジェクトはエデン空間に割り当てられます。すべて順調です。それがいっぱいになったら、GCが必要なので、古いオブジェクトを削除し、生きているオブジェクトをサバイバースペースに移動します。今のところまだ良い。しかし、次にエデンスペースを使い果たしたときには、難問があります。次のGCが登場し、エデンとサバイバースペースの両方のスペースをクリアしますが、スペースは連続していません。だからそれは良いですか

  1. エデンの生存者を、GCによってクリアされた生存者スペースの穴に収めようとしましたか?
  2. 断片化を排除するために、生存者空間内のすべてのオブジェクトを下に移動し、then生存者をそこに移動しますか?
  3. 「ネジを締めて、とにかくすべてを動かしています」と言うだけで、両方のスペースからすべての生存者を完全に別のスペース(2番目の生存者スペース)にコピーします。次のGCでシーケンスを繰り返しますか?

質問に対するサンの答えは明らかです。

72
Ryan Stewart

2つのサバイバースペースの役割は、マイナーガベージコレクションの操作後に逆転します

2つのサバイバースペース。これらは、少なくとも1つのマイナーガベージコレクションを生き残ったが、古い世代に昇格する前に到達不能になる別の機会を与えられたオブジェクトを保持します。そのうちの1つだけがオブジェクトを保持し、もう1つはほとんどの場合使用されません。

マイナーガベージコレクションの操作中に、ガベージであることが判明したオブジェクトはマークされます。コレクションを生き延びたエデン内のライブオブジェクトは、未使用のサバイバースペースにコピーされます。使用中のサバイバースペースのライブオブジェクトは、若い世代で回収される別の機会が与えられ、未使用のサバイバースペースにもコピーされます。最後に、使用中のサバイバースペースにある「古い」と見なされるライブオブジェクトは、古い世代にプロモートされます。

マイナーガベージコレクションの最後に、2つのサバイバースペースが役割を交換します。エデンは完全に空です。使用されているサバイバースペースは1つだけです。そして、古い世代の占有率はわずかに成長しました。ライブオブジェクトは操作中にコピーされるため、このタイプのガベージコレクタはコピーガベージコレクタと呼ばれます。

出典:上記はチャーリー・ハントとビヌ・ジョンによるJavaパフォーマンスの83ページからの抜粋です。

21
Neeraj Singh

若い世代:短期間住んでいた場所で、2つのスペースに分かれています:

エデンスペース:新しいオブジェクトがメモリプールに割り当てられます。ほとんどのオブジェクトは、作成後すぐに逆参照され、到達不能になるという仮定です。間接参照されていないオブジェクトは、新世代のガベージコレクターによってサバイバースペースにコピーされます。それらは、いくつかの特別な場合に古い世代プールに直接コピーされる場合があります。

サバイバースペース:これら2つの小さなスペースは、若い世代のガベージコレクションの生き残ったオブジェクトを保持します。生存しているオブジェクトは、ある生存者から別の生存者に(わずかな)回数コピーされます。これにより、より多くの間接参照オブジェクトを取得できます。

古い世代:長い間生きているオブジェクトを保持する最大のメモリプール。オブジェクトは、サバイバースペースを離れると、このプールにコピーされます。

パーマ生成:このかなり未知のプールは、すべてのクラスの情報を保持します。ほとんどのアプリケーションでは注意する必要はありません。多くのクラスを持ついくつかのアプリケーションに適応させる必要があるかもしれません。アプリケーションがクラスを永続的にロードおよびアンロードする場合も注意が必要な場合があります。

その他の利点:

  • メモリの断片化
  • GCのパフォーマンスが向上します

詳細を理解するには、次のリンクを参照してください。

http://www.scalingbits.com/javaprimer

http://Java.sys-con.com/node/84695

3
Premraj

現在のすべての答えはメモリの断片化について語っていますが、これもGCに世代がある別の理由です。

ランタイムは、「新しいオブジェクト」を指すすべての「古いオブジェクト」を記録します。これは、「ポインター」フィールドが更新されるたびに行われます。次に、「マイナー」GCが完了したら、「新しい」オブジェクトのみをスキャンする必要があります。

長年にわたって、「新しい」と「古い」だけでは不十分であることがわかりました。

2
Ian Ringrose

世代のすべてのインスタンスをあるスペースから別のスペースにコピーすることと、メモリアドレス順に世代のスペースの先頭にコピーすることの利点と欠点は何ですか?アイテムを順番に処理するには、おそらくアイテムごとに追加のポインターを追加する必要がありますが、「サバイバー」スペースのいずれかの必要性はなくなります。

1
supercat

ヒープメモリJava Javaヒープメモリと呼ばれる領域に作成されたオブジェクト。ヒープメモリは、JVMの起動時、ヒープメモリの増減時に作成されます。 when Java application running。ヒープメモリがいっぱいになると、ガベージコレクターは未使用のオブジェクトを削除するため、ガベージコレクターは新しいオブジェクト用のスペースを作成します。

ヒープメモリは、次の2つの領域(または世代)に分割されます。

1.ヤングスペース。 2.古いスペース。

1.若いスペースには、新しいオブジェクト用のエデンスペースがあり、2つのサバイバースペース(fromとto)があり、これら2つのサバイバースペースは常に同じサイズです。

2.Survivor Spacesはサバイバルオブジェクトの保存に使用されます。若いスペースがいっぱいになると、ガベージコレクターは特別な若いコレクションを実行して未使用のオブジェクトを削除します。古いスペース、したがって、より多くのオブジェクト割り当てのために若いスペースを解放します。

3. Edenスペースがいっぱいの場合、GCが実行されます。このEdenスペースにオブジェクトが存在する場合、それらはSurvivorスペースに移動されます。

4.若いスペースでは、GCは通常コピーアルゴリズムを使用します。これは高速で、毎回、生存オブジェクトは生存スペースの1つにコピーされます。

5.サバイバースペースがいっぱいの場合、残りのライブオブジェクトは古いスペースに直接コピーされます。

6.古いスペースでは、GCは通常、マークコンパクトアルゴリズムを使用します。

7.古いスペースがいっぱいになると、古いコレクションと呼ばれるプロセスでガベージが収集されます。古いスペースでは、長いライブタイムオブジェクトがそこに残ります。

8. OLDまたはPermパーツに対してGCを行っても、新しいオブジェクト用のスペースがなくなるとメモリ不足が発生します。

9.オブジェクトはガベージコレクション中に移動されます:eden-> survivor-> tenured(old space)

0
ASR

2人の生存者は、マークアンドコピーアルゴリズムの実装です。これらは若い世代のGCで使用されます。オプション3でRyanが述べたように here

enter image description here

0
Vikash