1. はじめに
本記事は、JVMにおけるGC(ガーベジコレクション)の観測と分析に焦点を当てた「後編」です。
チューニングには踏み込まず、取得した観測データ(jstat出力など)をどのように読み解くかについて説明していきます。
- 前編:GCの基本/発火タイミング
- 中編:jstatの使い方と読み方
- 後編(本記事):分析カタログと診断フロー
2. 診断フロー(まずはこれを確認)
[開始]
↓
[FGC > 0 ?]──Yes──>【重大】原因特定を最優先
(Old逼迫 / Metaspace / 断片化 / System.gc())
│No
↓
[YGCの周期は安定?]──No──> Eden小 or 割当過多(Young過多)を疑う
│Yes
↓
[Old(O%)は高止まり?]──Yes──> 昇格過多/巨大配列/キャッシュの疑い(Mixed効率も確認)
│No
↓
[Metaspace(M/CCS)は高い?]──Yes──> クラスロード過多/リークを点検
│No
↓
[GCT/稼働% は許容内?]──No──> YoungGC頻度や並行フェーズ負荷を再点検
│Yes
↓
【現状維持】(観測継続・履歴比較)
- 判断材料は中編で扱ったjstatの列(
E/O/M/CCS/YGC/FGC/YGCT/FGCT/GCT
)。 - ZGCの注意:FGCは基本0のまま。ZGCではポーズ指標(
YGCT
/GCT
の増え方)とアプリ指標(p99レイテンシ/CPU)を合わせて評価。
3. 指標のしきい値(観測のみの目安)
指標 | 目安 | 補足 |
---|---|---|
FGC | 0回 | 1回でも発生原因の特定価値あり |
GCT/稼働時間 | < 5% | Web/API一般目安。用途/SLAで調整 |
Old (O%) ピーク | < 80% | 連続ピーク/単調増は要注意 |
E (Eden%) | Young直前で高→直後に下がる | 周期の安定を重視 |
M/CCS | 高止まりしない | 動的クラス生成/再ロード頻発に注意 |
※しきい値は「出発点」。自分のベースラインを持ち、差分で異常を検知するのが実務的。
4. 代表パターン・カタログ
※ 例では -t
指定時のTimestamp
列を前提(Time
ではなくTimestamp
になります)
4.1 安定(G1)
Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.0 0 0 12 40 15 10 0 0.000 0 0.000 0.000
10.0 4 0 93 42 16 10 3 0.090 0 0.000 0.090
20.0 1 5 18 41 16 10 4 0.120 0 0.000 0.120
読み: Young周期は10秒前後で安定。Oldは滑らか、FGC=0、GCT は小さい → 健全。
4.2 Young 過多(Eden 小 / 割当過多)
Timestamp E O YGC YGCT GCT
0.0 10 35 0 0.000 0.000
1.0 95 36 3 0.060 0.060
2.0 93 37 6 0.120 0.120
読み: 1 秒ごとにYoung。割当レートがEdenに対し高い。周期を伸ばせるかを分析対象に。
4.3 Old張り付き(Mixedが効かない)
Timestamp E O YGC FGC GCT
0.0 10 70 0 0 0.000
30.0 90 85 12 0 0.200
60.0 88 88 24 1 0.600
読み: Old が80%近辺で高止まり → ついにFGC
。昇格過多/巨大配列/キャッシュを疑う(Mixed の効きも弱い)。
4.4 Metaspace高止まり
Timestamp M CCS FGC FGCT
0.0 40 18 0 0.000
30.0 85 45 0 0.000
60.0 92 48 1 0.300
読み: M/CCS
の伸びが止まらず、ついにFGC
。動的クラス生成/プラグイン/再ロードを点検。
(例:テンプレート/バイトコード生成系、熱リロード、OSGi/プラグイン等)
4.5 ZGC の読み方の例(低ポーズ型の観測)
Timestamp YGC YGCT FGC FGCT GCT
0.0 0 0.000 0 0.000 0.000
30.0 1 0.002 0 0.000 0.002
60.0 2 0.004 0 0.000 0.004
Timestamp YGC YGCT FGC FGCT GCT
0.0 0 0.000 0 0.000 0.000
30.0 1 0.002 0 0.000 0.002
60.0 2 0.004 0 0.000 0.004
読み: 回数/累積停止時間が小さく出る。レイテンシは良好だがCPU負荷は別途監視(低ポーズの代償で並行処理が多い)。
※ ZGCではE/O/S0/S1
の列はG1のようには解釈しない。停止時間とアプリ指標の相関で評価。
5. 計算式
- 割当速度(MB/s) ≒(Young直後→次Young直前の
EU
増分)÷ Young間隔(秒)÷ 1024(KB→MB換算) - 昇格速度(MB/s) ≒(Young直前/直後の
OU
増分)÷ Young間隔(秒) ÷ 1024 - 平均Youngポーズ(ms/回) ≒ ΔYGCT / ΔYGC × 1000(区間内でYoungが複数回なら平均)
- 区間のGC割合(%) ≒ ΔGCT / ΔTimestamp × 100(観測ウィンドウ内のGCオーバーヘッド)
※いずれも差分(Δ)を取るのがコツ(累積値をそのまま単発で割らない)。
6. 分析メモの例
### 観測条件
- 期間: 2025-08-22 10:00–10:30 (JST)
- 負荷: 60rps、90%読取 / 10%書込
- JVM: Java21, G1GC, -Xms2g -Xmx2g
- 採取: jstat -gcutil -t -h10 <pid> 5000 360
### 概要
FGC=0、Young周期≈12s、Oldピーク61%、GCT/稼働0.4% → 影響軽微。
### 事実(jstat要約)
- YGC=126(YGCT=7.4s)、FGC=0(FGCT=0s)
- O%: 平均44.7%、最大61.3%
- M/CCS: 平均28/10%、スパイクなし
### まとめ
- Young周期は安定、Oldも張り付きなし → 正常範囲。
- レイテンシSLO達成。要継続監視(リリース後の差分確認)。
### 次に見るもの(任意)
- 直近リリース前後の差分、p99レイテンシ、CPU/メモリ相関、アロケーションレート
7. ダッシュボード指標(観測向け)
- YGC/分, FGC回数, GCT/稼働%(GCオーバーヘッド)
- O%の p95/p99, E%が90%超の割合(周期の安定度)
- M/CCS の推移
- 併せてレイテンシ(p95/p99)/スループット/CPU/メモリを同じ時間軸で並置
8. 補助コマンド
jstat -gccause -t <pid> <interval> <count>
直近/現在の GC 原因を把握(FGC
や異常な Young が混じる区間で併用)jcmd <pid> GC.class_histogram
上位クラス占有で巨大配列/キャッシュを推定(Impact: High、本番での頻度に注意)jcmd <pid> VM.flags -all
実際の GC/ヒープ関連フラグの把握
9. まとめ
- 本記事ではGC観測データの分析視点にフォーカスしました。
- チューニングを行う前に、現象の正確な把握と解釈をすることが重要です。
- 履歴比較(正常時との比較)を第一にし、単発値ではなくトレンドと相関を重視してください。
- ChatGPTなどの生成AIが使える環境であれば、一時解析をAIに任せて概要を把握し、その後に自分でログを精査するという進め方も効率的でおすすめです。
- 3部構成でGCについて説明してきましたが、本記事がGC解析の助けとなれば幸いです。
10. 参考リンク
- 関連:Java 公式ドキュメント(Garbage Collection Tuning Guide)
https://docs.oracle.com/en/java/javase/21/gctuning/
コメント