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

JVMオプション

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

補足:Tomcatでの指定

 * CATALINA_OPTS に指定する
  => 具体的には、$CATALINA_HOME/bin/setenv.bat (Windows) に指定
【設定例】$CATALINA_HOME/bin/setenv.bat (Windows)
set CATALINA_OPTS=-XX:+HeapDumpOnOutOfMemoryError

■ コマンド

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
`#`項目`名称`説明
01S0CSurvivor 0 CapacitySurvivor 領域 0 の現在の容量[KB]
02S1CSurvivor 1 CapacitySurvivor 領域 1 の現在の容量[KB]
03S0USurvivor 0 UsedSurvivor 領域 0 の現在の使用量[KB]
04S1USurvivor 1 UsedSurvivor 領域 1 の現在の使用量[KB]
05ECEden Capacityエデン領域の現在の容量[KB]
06EUEden Usedエデン領域の現在の使用量[KB]
07OCOld CapacityOld 領域の現在の容量[KB]
08OUOld UsedOld 領域の現在の使用量[KB]
09MCMetaspace CapacityMetaspace領域の現在の容量[KB]
10MUMetaspace UsedMetaspace領域の現在の使用量[KB]
11CCSCCompressed Class Space Capacity圧縮されたクラス領域の現在の容量[KB]
12CCSUCompressed Class Space Used圧縮されたクラス領域の現在の使用量[KB]
13YGCYoung Garbage Collection若い世代の GC イベント数
14YGCTYoung Garbage Collection Time若い世代のガベージコレクション時間
15FGCFull Garbage Collectionフル GC イベント数
16FGCTFull Garbage Collection Timeフル GCガベージコレクション時間
17GCTGarbage Collection Total Timeガベージコレクション総時間

補足

 * メモリ領域の説明については、以下の関連記事を参照のこと
https://blogs.yahoo.co.jp/dk521123/33622631.html


■ 構文

 [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ガベージコレクション ( Barbage Collection; GC )

https://blogs.yahoo.co.jp/dk521123/37328410.html

Javaにおけるオブジェクトの使用メモリサイズの測る

http://blogs.yahoo.co.jp/dk521123/32941391.html

Instruction の getObjectSize で、オブジェクトの使用メモリサイズを測る

http://blogs.yahoo.co.jp/dk521123/32945695.html

Java のメモリ構造

https://blogs.yahoo.co.jp/dk521123/33622631.html

【フリーツール】【Java】メモリ監視ツール ~Eclipse Memory Analyzer~

https://blogs.yahoo.co.jp/dk521123/33092315.html