GC とメモリ管理
🐱 この章の目次
ガベージコレクションの基本
Python は 参照カウント を主なメモリ管理手法とし、循環参照のために世代別 GC を補助的に使います。 JVM は参照カウントを使わず、トレーシング GC がヒープ全体を走査して不要なオブジェクトを回収します。 この設計の違いが、パフォーマンス特性とチューニングの必要性に大きな差を生みます。
ヒープの世代構造
JVM のヒープメモリは Young 世代 と Old 世代 に分かれています。 新しいオブジェクトは Young 世代に割り当てられ、短命なオブジェクトはここで素早く回収されます。 長く生存するオブジェクトは Old 世代に昇格し、低頻度で回収されます。
┌─────────────────────────────────────────┐
│ JVM ヒープ │
├──────────────────┬──────────────────────┤
│ Young 世代 │ Old 世代 │
│ (短命オブジェクト) │ (長命オブジェクト) │
│ 高頻度 GC │ 低頻度 GC │
└──────────────────┴──────────────────────┘
GC アルゴリズムの選択
G1GC は JDK 9 以降のデフォルト GC で、レイテンシとスループットのバランスに優れています。 ZGC は JDK 21 で本番対応となった低レイテンシ GC で、最大停止時間を 1ms 未満に抑えます。 用途に応じて GC を選択できるのは、Python にはない JVM の柔軟性です。
# GC の選択(JVM 起動オプション)
java -XX:+UseG1GC -jar app.jar # G1GC(デフォルト)
java -XX:+UseZGC -jar app.jar # ZGC(低レイテンシ)
GC チューニングの基本
最低限押さえるべきオプションはヒープサイズの設定です。
java -Xms512m -Xmx2g -jar app.jar
# 初期ヒープ 最大ヒープ
| オプション | 意味 |
|---|---|
-Xms | 初期ヒープサイズ |
-Xmx | 最大ヒープサイズ |
-XX:+UseG1GC | G1GC を使用 |
-XX:MaxGCPauseMillis=200 | 目標停止時間(ms) |
Python との違い
Python ではメモリ管理を意識することはほとんどありません。 参照カウントがオブジェクトを即座に解放し、循環参照コレクタが残りを処理するためです。
JVM では GC の停止時間(Stop-the-World パーズ)がレスポンスタイムに影響するため、本番環境ではチューニングが重要です。 特にリアルタイム性が求められるサービスでは、GC の選択とヒープサイズの調整がパフォーマンスを左右します。