301


Scavenge GC と Full GC の処理の違いは何か教えて下さい。以下については理解しています。

  * Scavenge GC が Eden 領域がいっぱいになった時に実行される
  * MaxTenuringThreshold の回数文、S0 から S1 に移動が発生した場合に、OLD 領域への移動が発生する
  * Old がいっぱいになった時に Full GC が発生する。

つまり、Old に残っているオブジェクトは、どこからか参照されていて、それ故に残っていると考えられます。したがって、Full GC が Scavenge
GC と同様の処理である場合、Old のオブジェクトは、どこからか参照されていると判定されるので、破棄できないのではないかと思いました。

しかし、実際にはそんなはずは無いので、Full GC と Scavenge GC には、不要なオブジェクトを探索するアルゴリズムに差異があるのでは(Full
GC のほうが深く探索するなど)、と推測しているのですが裏付けとなる情報が得られていません。

よろしくお願いします。


CC BY-SA 3.0
2014-12-03T03:18:59.290
295
2014-12-17T02:26:49.627
2014-12-03T03:26:06.043
294
294
question
java gc アルゴリズム
Java における Scavenge GC と Full GC の違い


Scavenge GC の対象の Eden 領域などを含む NEW
領域は、直近で生成された短命なオブジェクトが残り、しきい値を超えた寿命を持つオブジェクトが OLD 領域に入るだけなので、OLD
領域は寿命の長いオブジェクトが入ることになります。ですので、どちらに居ても、他のオブジェクトから参照されているオブジェクトは破棄されません。

GC の方式としては、Scavenge GC はコピー方式で、Full GC
はマーク・アンド・スイープ方式が採用されている話があります(<http://www.atmarkit.co.jp/ait/articles/0704/24/news136.html>)。が、すこし情報が古いようですね。最近は、特に
Full GC 時の停止期間を少なくするために、コンカレントな GC を Full GC
に採用するのが一般的です(<http://d.hatena.ne.jp/wyukawa/20130103/1357211148>)。Java 7
以降だと、G1GC
という方式も出てきています(<http://nekop.hatenablog.com/entry/20140407/1396858038>)。


CC BY-SA 3.0
2014-12-03T04:15:50.650
301
2014-12-03T04:15:50.650
484
295
answer


HotSpot JVM は、世代別 GC
と呼ばれる仕組みを提供しています。理解している点として挙げられているNew領域とOld領域に分けてGCをするという仕組みです。  
生成されたばかりの若いオブジェクトがいるNew領域を対象にしたGCを Minor GC、長命オブジェクトがいるOld領域を対象にしたGCを Major GC
と呼びます。

また、HotSpot JVMは主なGCとして次のGCを提供しています。

  * Parallel GC
  * Concurrent Mark&Sweep GC
  * Garbage First GC

このうち、どのGCを利用するかは、Javaを起動する時のオプションによって決定されます。 HotSpot JVM はこれらの GC を世代別 GC
として実行しています。

と、ここまでが前提。

Scavenge GC、Full GCが何なのかというと、Parallel GCを選択した際のMinor GCとMajor GCです(※1)。
Scavenge GCはNew領域を対象にして、Full GCはOld領域を含む全領域(※2)を対象にしてGCします。  
なので、Scavenge GC ではOld領域の不要メモリは回収されません。Full GCによって回収されます。

※1：Concurrent Mark&Sweep GCを選択した場合でも実行されますが、質問内容的にParallel GCだと判断しました。
Concurrent Mark&Sweep GCについては手前味噌ですが以下の資料をどうぞ
<http://www.slideshare.net/YujiKubota/concurrent-marksweep-garbage-collection>

※2：状況によっては、一部領域が除外されます


CC BY-SA 3.0
2014-12-16T15:25:48.130
1792
2014-12-16T15:25:48.130
2511
295
answer


Javaが「世代別GC」を採用しているのはなぜかと言うと、寿命が短いオブジェクトが多いからです。逆に寿命が長いオブジェクトはなかなか不要にならない傾向があります。これが重要なポイントです。そのため、寿命が長いオブジェクトは非効率的なGCで止むを得ないが、寿命が短いオブジェクトは効率的にGCを実行したいという考えから、世代別GCを採用しています。

「[Qiitaの私の投稿](http://qiita.com/sipadan2003/items/a7acf7f0375d818b5045)」を参照してください。

New領域には、1個のEden領域と、2個のSurvivor領域があります。

まず、オブジェクトを生成したら、New領域内のEden領域に格納されますが、Eden領域が一杯になったら、Scavenge
GCが実行されます。そのとき不要オブジェクトはメモリから破棄されますが、生存オブジェクト（=参照が切れていないオブジェクト）はSurvivor領域に移動されます。

New領域(EdenとSurviovor)がまた一杯になったら、再びScavenge
GCが実行され、もう一つのSurvivor領域に生存オブジェクトが移動されます。New領域が一杯になるたびに、Scavenge
GCが繰り返されます。Scavenge
GCは、生存オブジェクトを2個のSurvivor領域の間を移動(コピー)させながらGCを実行するので、コピーGCとも呼ばれています。

Scavenge GCが数回実行されても生存しているオブジェクトは、Old領域に移動されます。そして、Old領域が一杯になったときにCMS
GC/Parallel Old GC/Full GCが実行されます（Parallel Old GCはFull GCのマルチスレッド版のようなものです)。

オプションでCMS GCを選択した場合は、Full GCよりもCMS GCが優先的に実行されますが、CMS
GCはコンパクション（=ハードディスクに対するデフラグと同じ）を行わないので、Old領域内に小さな空き領域が散らばっている状態を作ります。そのため、CMS
GCを実行しても、Old領域にオブジェクトを格納できない場合は、フォールバック（回避策）として自動的にFull GCが実行されます。

CMS GCとFull
GCの相違点は、前者はOld領域だけに対してアプリケーションを止めずにGCを行いますが、コンパクションは行いません。後者はOld領域だけでなくPermanent領域に対してアプリケーションを止めてしまいますが、コンパクションを兼ねています。


CC BY-SA 3.0
2014-12-17T01:44:27.377
1832
2014-12-17T02:26:49.627
2014-12-17T02:26:49.627
4278
4278
295
answer