Javaの基本的なGCの仕組みについて記述します。
FullGCは単純です。Mark&Sweepで行なわれます。Mark&Sweepは最初のフェイズで使用しているオブジェクトのマーキングを行い、次のフェーズでマーキングされていないオブジェクトを削除します。ことのき「使用をしている」という判断は、ルートからたどります。その為、VMのメモリ上に存在するすべてのオブジェクトを対象とします。
scavengeGCは世代別GCとcopyGCの組み合わせで行なわれます。copyGCは使用しているオブジェクトを別の領域にコピーし、元の領域を完全に開放します。JavaのscavengeGCの場合には、New領域のFromとToを行ったりきたりするイメージです。
重要なのは「使用をしている」という判断です。「使用をしている」という判断は、ルートからたどり使用しているものにマーキングしていきます。しかしFullGCのMark&Sweepと異なり、一部のオブジェクトのみを対象とします。Javaの場合、New領域しか対象にしません。つまりルートからたどるという意味ではFullGCと同じなのですが、Old領域は調査の対象にしないため、調査対象オブジェクトはその分減ります。
しかし、Old領域からNew領域へ参照のあるオブジェクトもありえます。これを救う為に、Old領域からNew領域への参照が作られたときには、そのポインタがリストに追加されます。そして、このリストのオブジェクトもルートと同じように検索されます。
このような違いがあるため、scavengeGCはFullGCよりも少ないオブジェクト数を対象にすることが可能で、また短い時間で終わるのです。
参考:GCアルゴリズム詳細解説
※FullGCの説明は、多くのサイトで紹介されています。しかし、scavengeGCの仕組みは説明していないか、あいまいな内容しか記述していないサイトが多いです。特に「使用をしている」という判断のロジックの部分が非常に大切なのに、その肝心な説明が欠けているサイトが少なくありません。私も答えにたどり着くまでに時間がかかりました。
おまけどういうわけか、同じGCでも複数の呼び名を持っています。呼び名の種類と対になる呼び名をまとめておきます。
2010/06/15
2012/08/05 おまけ追記 |
Knowledge >