【Java】JVMのメモリ情報を出力させる

◾️はじめに

https://dk521123.hatenablog.com/entry/2018/01/01/200400

でJavaのGCについて扱ったが、
今回は、JVMのメモリ情報を出力させる方法について、メモしておく

【1】JVMオプション

-XX:+HeapDumpOnOutOfMemoryError
# オプション 説明
1 -XX:+HeapDumpOnOutOfMemoryError OutOfMemoryErrorが発生したときにダンプファイルを出力

補足:Tomcatでの指定

* CATALINA_OPTS に指定する
 => 具体的には、$CATALINA_HOME/bin/setenv.bat (Windows) に指定

【設定例】$CATALINA_HOME/bin/setenv.bat (Windows)

set CATALINA_OPTS=-XX:+HeapDumpOnOutOfMemoryError

【2】コマンド

jpsコマンドで、JavaプロセスのプロセスIDを調べるから、以下のコマンドを実行する

 [1] jstatコマンド を利用する ... 
 [2] jmapコマンド を利用する  ... ヒープやNativeメモリ情報を調べる
 [3] jcmdコマンド を利用する  ... メモリ消費量の多い順にリストアップ

使用例

[1] jstatコマンド を利用する

# [1] jpsコマンド : JavaプロセスのプロセスIDを調べる
jps

[2] jstatコマンド

jstat -gc[1]で調べたプロセスID】 1000

https://docs.oracle.com/javase/jp/8/docs/technotes/tools/windows/jstat.html

# 項目 名称 説明
01 S0C Survivor 0 Capacity Survivor 領域 0 の現在の容量[KB]
02 S1C Survivor 1 Capacity Survivor 領域 1 の現在の容量[KB]
03 S0U Survivor 0 Used Survivor 領域 0 の現在の使用量[KB]
04 S1U Survivor 1 Used Survivor 領域 1 の現在の使用量[KB]
05 EC Eden Capacity エデン領域の現在の容量[KB]
06 EU Eden Used エデン領域の現在の使用量[KB]
07 OC Old Capacity Old 領域の現在の容量[KB]
08 OU Old Used Old 領域の現在の使用量[KB]
09 MC Metaspace Capacity Metaspace領域の現在の容量[KB]
10 MU Metaspace Used Metaspace領域の現在の使用量[KB]
11 CCSC Compressed Class Space Capacity 圧縮されたクラス領域の現在の容量[KB]
12 CCSU Compressed Class Space Used 圧縮されたクラス領域の現在の使用量[KB]
13 YGC Young Garbage Collection 若い世代の GC イベント数
14 YGCT Young Garbage Collection Time 若い世代のガベージコレクション時間
15 FGC Full Garbage Collection フル GC イベント数
16 FGCT Full Garbage Collection Time フル GCガベージコレクション時間
17 GCT Garbage Collection Total Time ガベージコレクション総時間

[2] jmapコマンド を利用する
http://muraken720.hatenablog.com/entry/20100724/p2 http://qiita.com/kaikusakari/items/9b7c3d1fb524eb6aa348 http://qiita.com/opengl-8080/items/64152ee9965441f7667b

【3】構文

[1] Runtime.getRuntime()を利用する
[2] ManagementFactory.getMemoryMXBean()を利用する

サンプル

MemoryInfoHelper.java

package memory;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.text.DecimalFormat;

public class MemoryInfoHelper {
   private static DecimalFormat formatNumber = new DecimalFormat("#,###KB");
   private static DecimalFormat formatRatio = new DecimalFormat("##.#");
   
   public static String getMemoryInfo() {
      long free = Runtime.getRuntime().freeMemory() / 1024;
      long total = Runtime.getRuntime().totalMemory() / 1024;
      long max = Runtime.getRuntime().maxMemory() / 1024;
      long used = total - free;
      double ratio = (used * 100 / (double) total);

      return String.format("Total : %s, Momory Use : %s(%s%%), Max memory : %s",
            MemoryInfoHelper.formatNumber.format(total),
            MemoryInfoHelper.formatNumber.format(used),
            MemoryInfoHelper.formatRatio.format(ratio),
            MemoryInfoHelper.formatNumber.format(max));
   }

   public static String getHeapMemoryInfo() {
      MemoryMXBean bean = ManagementFactory.getMemoryMXBean();
      MemoryUsage heapUsage = bean.getHeapMemoryUsage();

      long init = heapUsage.getInit();
      long used = heapUsage.getUsed();
      long committed = heapUsage.getCommitted();
      long max = heapUsage.getMax();
      
      return MemoryInfoHelper.getMemoryInfo(init, used, committed, max);
   }
   
   public static String getNonHeapMemoryInfo() {
      MemoryMXBean bean = ManagementFactory.getMemoryMXBean();
      MemoryUsage nonHeapUsage = bean.getNonHeapMemoryUsage();

      long init = nonHeapUsage.getInit();
      long used = nonHeapUsage.getUsed();
      long committed = nonHeapUsage.getCommitted();
      long max = nonHeapUsage.getMax();
      
      return MemoryInfoHelper.getMemoryInfo(init, used, committed, max);
   }
   
   private static String getMemoryInfo(
         long init, long used, long committed, long max) {
      return String.format(
            "Init : %s, Momory Used : %s, Committed : %s, Max : %s",
            MemoryInfoHelper.formatNumber.format(init),
            MemoryInfoHelper.formatNumber.format(used),
            MemoryInfoHelper.formatNumber.format(committed),
            MemoryInfoHelper.formatNumber.format(max));
   }
}

Main.java (使用者)

package memory;

public class Main {
   public static void main(String[] args) {
      System.out.println(MemoryInfoHelper.getMemoryInfo());
      System.out.println("[Heap Memory]");
      System.out.println(MemoryInfoHelper.getHeapMemoryInfo());
      System.out.println("[Non-Heap Memory]");
      System.out.println(MemoryInfoHelper.getNonHeapMemoryInfo());
   }
}

出力結果例

Total : 15,872KB, Momory Use : 875KB(5.5%), Max memory : 253,440KB
[Heap Memory]
Init : 16,777,216KB, Momory Used : 986,232KB, Committed : 16,252,928KB, Max : 259,522,560KB
[Non-Heap Memory]
Init : 35,815,424KB, Momory Used : 11,955,440KB, Committed : 36,306,944KB, Max : 123,731,968KB

参考文献

http://itpro.nikkeibp.co.jp/article/COLUMN/20060605/239936/
http://sattontanabe.blog86.fc2.com/blog-entry-49.html
https://qiita.com/YN0314/items/5e5c57d52ac1379daf6d

関連記事

Javaガベージコレクション
https://dk521123.hatenablog.com/entry/2018/01/01/200400
Java 〜 メモリ構造 〜
https://dk521123.hatenablog.com/entry/2014/06/14/235331
Java の Stop-The-World の調査方法
https://dk521123.hatenablog.com/entry/2025/03/10/005354
メモリ分析ツール ~ JFR / JMC ~
https://dk521123.hatenablog.com/entry/2014/03/17/234107
メモリ分析ツール ~ Memory Analyzer ~
https://dk521123.hatenablog.com/entry/2014/02/24/235516
メモリ分析ツール ~ jattach ~
https://dk521123.hatenablog.com/entry/2025/03/12/002316
Javaにおけるオブジェクトの使用メモリサイズの測る
Instruction の getObjectSize で、オブジェクトの使用メモリサイズを測る