プロジェクト

全般

プロフィール

Javaガベージコレクション

ガベージコレクションの選択

JavaVMは、複数のガベージコレクターが搭載されており、利用者がオプションで選択できるようになっています。

ガベージコレクションの種類

JDK 1.3以降、世代別ガベージコレクション(GC)が使われています。世代別GCは、若い世代のヒープ領域を対象とするマイナーGC、旧い世代のヒープ領域を対象とするフルGCで構成されます。世代別GCにもいくつかガベージコレクターの種類があります。

Java SE 8に搭載されているGCの種類

  • シリアルコレクター
    単一CPU(スレッド)でGC処理を実行する。マイナーGC/フルGCともに処理中はアプリケーションを停止させるStop-the-world(STW)あり。小さなヒープ(100MB以下)を対象とする。
  • パラレルコレクター(スループット型)
    複数CPU(スレッド)でGC処理を実行する。マイナーGC/フルGCともにSTWあり。単位時間あたりのGC処理効率を停止時間よりも優先する。
  • Concurrent Mark Sweep(CMS)
    可能な限りアプリケーションの動作と並行してGC処理を実行し、GC処理によるアプリケーション停止時間(STW)を極力少なくする。マイナーGCはSTWあり、フルGCは基本STWなし(markフェーズで短時間のSTWあり)、CMSが機能しなくなったとき(断片化の著しい進行、CPUリソース不足など)はシリアル型のフルGCを実施(コンパクションなど)。
  • G1GC
    可能な限りアプリケーションの動作と並行してGC処理を実行し、GC処理によるアプリケーション停止時間(STW)を極力少なくする。大きなヒープ(おおよそ4GB以上)を主な対象とする。フルGCもコピーコレクターを使用しコンパクションも行われる。

どれを選択するかはトレードオフの問題です。

  • 出典:「Javaパフォーマンス」(オライリー刊 2015年)

GCの種類補足

GC種類 若い世代のGC 旧い世代のGC
シリアルコレクター STWなシリアルScavenger STWなシリアルMark-Sweep-Compact
パラレルコレクター STWなパラレルScavenger STWなパラレルMark-Sweep-Compact
CMS STWなパラレルScavenger1 Concurrent Mark-Sweep
G1GC Fully-young collection Partially-young collection

1 パラレルコレクターの並行Scavengerとは違う、CMSと連携する"ParNew"。性能はやや遅い模様。

パラレルScavenger

  • STWあり、複数のGCスレッド

CMS

  • アプリケーションと並行して(Concurrent)GCの処理を行う。但し、GC処理の一部ではアプリケーションを停止させる
    • マイナーGC: ここはParallel Scavenger(並列コピーGC)が使われる
    • メジャーGCのうち、初期マーク処理とリマーク処理

G1GC

  • ヒープを等サイズのリージョンに分割し、リージョン単位でGCを行う。
  • GCの対象とするリージョンを選び、リージョン内の生存オブジェクトを別の空きリージョンへコピーした後、そのリージョンを初期化(空きリージョン)とする
  • 並行マーキングと退避から構成
  • 並行マーキングは、1.初期化マーク/2.並行マーク/3.最終マーク/4.生存オブジェクトカウント/5.後始末の5フェーズで、STWは1.と3.と5.
  • 退避は、1.回収集合選択/2.ルート退避/3.退避の3つで、いずれもSTW
  • マイナーGC(Fully-young collection)は、すべての若い世代リージョンを回収集合として選択
  • メジャーGC(Partially-young collection)は、すべての若い世代リージョンと一部の旧い世代リージョンを回収集合として選択
  • 若い世代リージョンには、生成リージョンと残存リージョンがある

デフォルトで使われるガベージコレクタ

Java SE 8

OS JavaVM リソース ガベージコレクタ
Windows 32bit シリアルコレクタ
64bit パラレルコレクタ
Linux 32bit 1CPUまたは2GBメモリ未満 シリアルコレクタ
2CPU以上かつ2GBメモリ以上 パラレルコレクタ
64bit パラレルコレクタ

CMSとG1GCを使うにはJavaVMオプションで明示的に指定します。

どのガベージコレクションを選択するか

大雑把には次の指針になります。

  • CPU(コア)が1つならシリアルGC
  • CPU(コア)が複数あり、STWの平均時間を短くしたい、アプリケーション実行時のCPUリソースに余裕が少ない場合、パラレルGC
  • アプリケーション実行時のCPUリソースに余裕があり、GCの処理量(オーバーヘッド)は増えてもSTWのワースト時間を最小限にしたい場合、CMSまたはG1GC
    • ヒープサイズが大きい場合、G1GC
    • 断片化が発生しやすい場合、G1GC

ガベージコレクションの指定

JavaVM起動時のオプションで選択したガベージコレクションの設定をします。

使用するガベージコレクタの指定

Java SE 8での指定です。

ガベージコレクタ種類 JavaVM起動オプション
シリアルコレクター -XX:+UseSerialGC
パラレルコレクター -XX:+UseParallelGC
CMS -XX:+UseConcMarkSweepGC
G1GC -XX:+UseG1GC

GCが使用するCPU(スレッド)数

パラレル型GCの使用CPU数

次の値がパラレル型GC(パラレルコレクタ、G1コレクタ)で使用する並列数(CPU数)です。
通常は、実行するPCのCPU数(スレッディング型のCPUの場合はコア数ではなくスレッド数)です。

    uintx ParallelGCThreads                         = 4                                   {product}
  • 2コア4HTのIntel Coreプロセッサ上でのデフォルト値

ヒープメモリ

ヒープメモリのサイズ

デフォルトのサイズ

若い世代と古い世代の配分

若い世代の中のEdenとSurvivorの配分

ヒープメモリ上のオブジェクト

オブジェクト・ヘッダー

ヒープメモリ上に格納するオブジェクト(インスタンス)のメモリ構造は、先頭にオブジェクト・ヘッダーが置かれる。

  • 非配列のオブジェクト
markワード 32bit版なら4バイト、64bit版なら8バイト
klassワード 32bit版/圧縮OOP有効な64bit版なら4バイト、圧縮OOP無効な64bit版なら8バイト
gap 4バイト、配置ルールで必要なときに置かれる(いつ?)
インスタンス・フィールド クラスの定義次第
  • 配列のオブジェクト
markワード 32bit版なら4バイト、64bit版なら8バイト
klassワード 32bit版/圧縮OOP有効な64bit版なら4バイト、圧縮OOP無効な64bit版なら8バイト
lengthワード 4バイト
gap 4バイト、配置ルールで必要なときに置かれる(いつ?)
インスタンス・フィールド
  • 圧縮OOPが有効なのは次のAND条件
    • -Xmxが未指定、または-Xmxで指定したサイズが32GB未満
    • -XX:-UseCompressedOopsをJavaVM起動オプションに指定していない
  • gapは配置ルールで必要な場合
  • 圧縮OOPが有効のときに32bitの管理ポインタと64bitポインタとの変換する方法
    • ヒープサイズが4GB以下のときは直接アドレッシング(ヒープが仮想メモリ空間の0~4GBのアドレスに位置する)
    • ヒープサイズが4GB超から32GBまでのときは、オブジェクトは8バイト境界に置かれる前提でポインタを圧縮
    • ヒープサイズが32GB超のときはベースアドレスと8バイト境界の組み合わせが必要になるのでklassワードは64bitに戻る(?)

技術情報へのリンク

GC総合

CMS

G1GC

HOL5429_Tuning_Low-Pause_Garbage_Collection.pdf - JavaOne 2013 SF (955 KB) 高橋 徹, 2016/06/21 08:54

クリップボードから画像を追加 (サイズの上限: 1 GB)