JavaVMのチューニングメモ †
ヒープ領域の構造 †
ヒープ領域は、下図のようにPermanent、New/Old領域に分けられる。
New領域はさらにEden領域とSurvivor領域に分けられる。
また、Survivor領域は、さらにFrom、To領域に分けられる。
Permanent領域 | New/Old領域 |
New領域 | Old領域 |
Eden領域 | Survivor領域 |
From領域 | To領域 |
各領域の役割、使用用途は下記の通り。
領域 | 説明 |
Permanent領域 | クラスの静的情報が配置される領域。(メソッド定義、フィールド定義、定数、および static 宣言されているフィールドの値など) |
New/Old領域 | 生成されたオブジェクト(インスタンス)が配置される領域。ここがGCの対象になる。 |
Eden領域 | 生成されたオブジェクトが最初に配置される領域。 |
Survivor領域 | ScavengeGCを生き残ったオブジェクトがここに移動される。 |
From | 次のGC時にTo領域になる。(FromとToが入れ替わる) |
To | ScavengeGCを生き残ったオブジェクトが最初に移動される領域 |
※JSPは、クラスを動的にロードする為、JSPを動作させているJava VMのPermanent領域の使用量は動的に増える。
基本的なGC †
- ScavengeGC(マイナーGC)
・NEW領域のみを対象とした短時間で終了するガベージ・コレクションであり、頻繁に実施される。
・前回のScavengeGC時のFrom領域とTo領域は互いに入れ替わる。※1
・ScavengeGCを生き残った回数が、しきい(※2)値を上回るオブジェクトについて、OLD領域への移動を行う。
※1 前回のScavengeGCでオブジェクトの移動先とされたTo領域は、次回のScavengeGCではFrom領域として扱われ、
このFrom領域とEden領域にある使用中のオブジェクトが、再びTo領域に移動される。
※2 しきい値はVM起動オプション -XX:MaxTenuringThreshold で指定可能。
- FullGC(メジャーGC)
・NEWとOLD両方の領域を対象とした大がかりなガベージ・コレクションであり、比較的低い頻度で実施される。
・FullGCが行われている間は、アプリケーションのスレッドは停止される。
・パーマネントがいっぱいになったときもフルGCが実行される。
コンカレントGC †
コンカレントGCはJ2SE 1.4から使用できるGC方式で、Old世代のGCをアプリケーションスレッドと並列に実行する。
◆コンカレントGCの問題点
・コンカレントGC実行中はGCスレッドが動作している分、負荷が高くなる為、
全体的なスループット(ある単位時間当たりの処理能力)は下がり、応答時間も遅くなる。
・コンカレントGCでは、New世代領域に関連するオプションのデフォルト値として「-XX:SurvivorRatio=1024 -XX:MaxTenuringThreshold=0」
が設定される為、1回のScavengeGCで回収されなかった短命オブジェクトはすぐにOld世代領域に移動してしまう。
その為、Old領域の使用量が上がりやすくなり、FullGCの回数が増えてしまう。
→ チューニングが必要。(VMオプションを参照)
VMオプション †
ヒープサイズのオプション
パラメータ名 | 説明 | デフォルト値 |
-Xms | 最小ヒープサイズを設定する | -Xms2M |
-Xmx | 最大ヒープサイズを設定する | -Xmx64M |
GCのオプション(デフォルトはOSごとに異なる為、”一般的”と思われる値を記載)
パラメータ名 | 説明 | デフォルト値 |
-XX:NewSize(-Xmn) | New世代領域に割り当てるサイズを指定。(サイズで指定) | |
-XX:MaxNewSize | New世代領域の最大ヒープサイズを設定する | |
-XX:NewRatio | New世代領域に割り当てるサイズを指定。(Old世代領域との比率で指定) | |
-XX:SurvivorRatio | Eden領域とSurvivor領域のサイズを比率で指定 ※Eden領域のサイズをFromまたはTo領域のサイズで割った値(FromとTo領域は同じサイズ) | 8?(EdenはFrom/Toの8倍) コンカレントGCを使用時は1024 |
-XX:MaxTenuringThreshold | New世代領域で、この値で指定する回数のマイナーGCを超えて生き残るとOld世代領域に移動する | コンカレントGCを使用時は 0 |
-XX:TargetSurvivorRatio | Survivor領域がいっぱいと判断される使用率 | 50% |
-XX:+UseConcMarkSweepGC | コンカレントGCの有効化 | |
-XX:+CMSParallelRemarkEnabled | メジャーGCのRemarkフェイズをマルチスレッドで実行 | |
-XX:+UseParNewGC | マイナーGCをマルチスレッドで実行 | |
-XX:PermSize | Permanent領域の初期サイズ | 1MB |
-XX:MaxPermSize | Permanent領域の最大サイズ | 64MB |
-XX:+PrintGCDetails | GCログの詳細を出力する | |
-Xloggc:ファイルPATH | GCログを指定したファイルに出力する | |
-verbose:gc | GCログを出力する | |
チューニングのコツ †
- 初期サイズと最大サイズを同じにする事で、サイズ調整にかかるコストが軽減される場合が多い。
- コンカレントGC、パラレルGCを使用し、GCパラメータを適切に設定する。(コンカレントGCのデフォルト値だとマズい)
- GCが疑わしい場合は Java起動オプション(-verbose:gc)でGCログを取得する。※HP JVMの場合-Xverbosegc が使える。