環境: Java 11

jcmdのヒープ・ヒストグラムでJavaヒープを分析する

jcmdでヒープ・ヒストグラムを作成すると、現在のヒープにおいて、どのクラスのインスタンスが、何個存在し、何バイト占めているかを知ることができる。

$ jcmd 0 GC.class_histogram

0の部分は通常JavaのPIDを指定するが、1プロセスしか動いていなければ0でよい。

-allオプション

GC.class_histogram

リファレンスにはGC.class_histogram-allオプションが存在することが記載されている。

GC.class_histogram [options]
Javaヒープの使用状況に関する統計情報を示します。
影響: 高 — Javaヒープ・サイズとJavaコンテンツによって異なります。

—all: (オプション) 到達不能なオブジェクトを含め、すべてのオブジェクトを検査します(BOOLEAN、false)

この記載だと、-allを毎回必ずつけなければいけないようには思えなかったのだが、-allをつけないとフルGCが走ってしまうようだ。調査中にフルGCを走らせて状況を変化させないように、-allは毎回つけたほうがいいのではないか?

GC.heap_dump

GC.heap_dumpのリファレンスにはフルGCのことについて明確に記載されている。

GC.heap_dump [options] [arguments]
JavaヒープのHPROF形式のダンプを生成します。
影響: 高 — Javaヒープ・サイズとJavaコンテンツによって異なります。-allオプションを指定されていないかぎり、フルGCを要求します。

-all: (オプション) 到達不能なオブジェクトを含む、すべてのオブジェクトをダンプします(BOOLEAN、false)

フルGCが走ることの確認

リファレンスに明確に記載されていないGC.class_histogramでも-allオプションの有無でフルGCするかしないかが変わることを、実際に確認してみる。

フルGCの回数を確認するにはjstat -gcutil プロセスIDでFGCの列を見る。

## 現在のフルGCの回数を確認する
$ jstat -gcutil プロセスID

## -allオプションありで実行する
$ jcmd 0 GC.class_histogram -all

## フルGCの回数が変わっていないことを確認する
$ jstat -gcutil プロセスID

## -allオプションなしで実行する
$ jcmd 0 GC.class_histogram

## フルGCの回数が1回増えていることを確認する
$ jstat -gcutil プロセスID