jcmd / jmap でJavaメモリを調査する実務手順

  • URLをコピーしました!

Javaアプリケーションがメモリ不足(OOM)で落ちる、もしくはメモリ使用量が異常に増え続ける場合、 jcmd / jmap は最も信頼できる調査ツールです。 本記事では「障害発生時に何から実行すべきか」「出力結果をどう解釈するか」を 実務手順ベースで解説します。

目次

この記事でわかること

本記事を読むことで、Javaプロセスの特定からヒープ使用状況の確認、 ヒープダンプ取得、リークの兆候判定までを一連の流れで理解できます。 また、OOM発生前にやるべき調査と、やってはいけない操作も把握できます。

jcmd / jmap とは何か

jcmdとは

jcmd は JVM に対してコマンドを送信し、状態取得や操作を行う公式ツールです。 jstat や jmap の上位互換的な位置づけで、近年はこちらが推奨されています。

jmapとは

jmap は主にヒープメモリの詳細情報取得に特化したツールで、 ヒープダンプの取得やオブジェクト分布確認に使われます。

【STEP1】Javaプロセスを特定する

まず対象のJavaプロセスID(PID)を特定します。

jps -l

出力例:

12345 com.example.MyApplication
67890 org.apache.catalina.startup.Bootstrap

PID(例:12345)を以降の調査で使用します。

【STEP2】ヒープ使用状況を即座に確認する(最重要)

OOM直前・メモリ高騰時に最優先で実行すべきコマンドです。

jcmd 12345 GC.heap_info

確認ポイント:

  • used が max に近づいていないか
  • Old Gen が逼迫していないか

この時点で Old領域が常に高止まりしている場合、 メモリリークの可能性が非常に高いと判断できます。

【STEP3】ヒープ全体の利用状況を確認する

jcmd 12345 GC.heap_summary

ここでは以下を見ます。

  • Young / Old の比率
  • GC後も解放されない領域があるか

GC後も Old Gen が減らない場合は、リークまたはキャッシュ肥大が疑われます。

【STEP4】クラス別オブジェクト数を確認する

どのクラスがメモリを消費しているかを確認します。

jcmd 12345 GC.class_histogram

注目すべきポイント:

  • Object 数が異常に多いクラス
  • byte サイズが突出しているクラス

例:

num     #instances     #bytes  class name
1:      5000000        400000000  java.lang.String

String や Map 系が多い場合、キャッシュ・セッション保持が原因の可能性があります。

【STEP5】ヒープダンプを取得する(最終手段)

サービス影響を理解した上で、必要な場合のみ実施します。

jcmd 12345 GC.heap_dump /tmp/heapdump.hprof

⚠ 注意点:

  • ディスク容量を大量に消費する
  • 取得中に一時的な性能低下が発生する

取得後は Eclipse MAT / VisualVM などで解析します。

jmapを使う場合(旧環境・補助用途)

ヒープ使用状況

jmap -heap 12345

ヒストグラム

jmap -histo 12345 | head

ヒープダンプ

jmap -dump:live,format=b,file=/tmp/heap.hprof 12345

※ jmap は STW(Stop The World)が発生しやすいため、 本番では jcmd を優先してください。

よくある失敗パターン

  • OOM発生後に実行しても意味がない
  • PIDを間違えて別プロセスを調査
  • ヒープダンプ取得でディスク枯渇

実務でのおすすめ調査順

  1. jps でPID特定
  2. jcmd GC.heap_info
  3. jcmd GC.class_histogram
  4. 必要に応じて heap_dump

まとめ

jcmd / jmap は「Javaがなぜメモリで死ぬのか」を可視化する最強ツールです。 特に GC.heap_info → class_histogram の流れは、 OOM原因特定の王道パターンです。

目次