以下の内容はhttps://blog1.mammb.com/entry/2026/02/25/200910より取得しました。


Java Native Memory Tracking でネイティブメモリの利用状況を確認する


Native Memory Tracking とは

NMT(Native Memory Tracking) は Hotspot VM の機能。

JVM内部で実行されるネイティブメモリ割り当てを追跡できる(ただし JNIコードなどのJVM外部で割り当てられたネイティブメモリは追跡できない)。

NMT を利用するには JVM オプションを指定する(デフォルトは off)。

-XX:NativeMemoryTracking=off|summary|detail

summary で確認し、より詳細が必要な場合に detail を指定すると良い。

detail を指定するとメソッド単位でメモリ割り当てを確認できる。

有効化すると JVM は、malloc/free および mmap/munmap の呼び出しにフックして、メモリ使用量を計算する。 JVMのパフォーマンスは 5-10% 低下するとされている。


Native Memory の確認

NMT を有効化したら、jps で PID を確認し、jcmd でメモリの割り当て状況を確認できる。

jps -l

jcmd <pid> VM.native_memory scale=MB

以下のような出力が得られる(scale=MB を指定しない場合はバイト単位の出力となる)。

jcmd <pid> VM.native_memory scale=MB
<pid>:

Native Memory Tracking:

(Omitting categories weighting less than 1MB)

Total: reserved=5400MB, committed=73MB
       malloc: 11MB #84202, peak=54MB #52102
       mmap:   reserved=5389MB, committed=62MB

-                 Java Heap (reserved=4008MB, committed=18MB)
                            (mmap: reserved=4008MB, committed=18MB, at peak)

-                     Class (reserved=1024MB, committed=4MB)
                            (classes #4874)
                            (  instance classes #4415, array classes #459)
                            (mmap: reserved=1024MB, committed=4MB, at peak)
                            (  Metadata:   )
                            (    reserved=64MB, committed=13MB)
                            (    used=13MB)
                            (    waste=0MB =1.12%)
                            (  Class space:)
                            (    reserved=1024MB, committed=4MB)
                            (    used=4MB)
                            (    waste=0MB =1.99%)

-                    Thread (reserved=22MB, committed=1MB)
                            (threads #22)
                            (stack: reserved=22MB, committed=1MB, peak=1MB)

-                      Code (reserved=245MB, committed=13MB)
                            (malloc=3MB tag=Code #17420) (at peak)
                            (mmap: reserved=242MB, committed=10MB, at peak)

-                        GC (reserved=13MB, committed=0MB)
                            (mmap: reserved=13MB, committed=0MB, at peak)

-                  Compiler (reserved=0MB, committed=0MB)
                            (arena=0MB #6) (peak=44MB #15)

-                  Internal (reserved=2MB, committed=2MB)
                            (malloc=1MB tag=Internal #8798) (at peak)

-                    Symbol (reserved=3MB, committed=3MB)
                            (malloc=2MB tag=Symbol #38061) (at peak)

-    Native Memory Tracking (reserved=1MB, committed=1MB)
                            (tracking overhead=1MB)

-        Shared class space (reserved=16MB, committed=15MB, readonly=0MB)
                            (mmap: reserved=16MB, committed=15MB, peak=15MB)

-               Arena Chunk (reserved=0MB, committed=0MB)
                            (malloc=0MB tag=Arena Chunk #57) (peak=49MB #1006)

-                 Metaspace (reserved=64MB, committed=13MB)
                            (mmap: reserved=64MB, committed=13MB, at peak)

それぞれの用途で、どれだけのメモリが利用されているかが committed の値から分かる。

#付の数字はカウントを示す(例えば classes #4885 は4,885クラスが読み込まれたことを示す)。

以下の出力は Metaspace 内の Class space が 4,874 個のクラスが読みで 4MB を消費していることがわかる。

Class (reserved=1024MB, committed=4MB)
      (classes #4874)
      (  instance classes #4415, array classes #459)
      (mmap: reserved=1024MB, committed=4MB, at peak)

JDK 21~22でNMTの出力が改良されている。NMT: Display peak values, NMT: Make peak values available in release builds。 その時点の値に加え、peak としてピーク値を合わせて出力するようになった(カウント値はピークサイズに達した時点のカウント)。

表示内容に関する詳細なドキュメントは無いので、以下を見るのが早い。

https://github.com/openjdk/jdk/blob/master/src/hotspot/share/nmt/memReporter.cpp


NMT カテゴリ

カテゴリには以下がある。

カテゴリ 説明
Java Heap Javaヒープ
Class クラスメタデータ(圧縮クラスポインタ Compressed Class Pointers が参照する Klass 構造体)
Thread スレッド・データ構造、リソース領域、ハンドル領域などを含む、スレッドによって使用されるメモリ
Code バイトコードをアセンブリ命令にコンパイルする際のコードキャッシュ
GC カードテーブルなどのGCによるデータ使用(記憶集合(remembered sets)を除く)
GCCardSet GCの記憶集合(remembered sets)により使用されるデータ(G1GCのみ)
Compiler コードを生成するときにコンパイラによって使用されるメモリー・トラッキング
Internal コマンドライン・パーサー、JVMTI、プロパティおよびその他によって使用されるメモリーなど、前述のカテゴリに該当しないメモリ
Other カテゴリで分類できないもの
Symbol シンボルで利用されるメモリ(String Table / Runtime Constant Pool)
Native Memory Tracking NMTによって使用されるメモリ
Shared class space Class Data Sharing のメモリマッピング
Arena Chunk アリーナのチャンク・プール内のチャンクによって使用されるメモリ
Metaspace クラスメタデータ(Classカテゴリ内の Metadata と同)
Logging ロギングによって使用されるメモリ
Arguments 引数用のメモリ
Module モジュールによって使用されるメモリ

MetaspaceSize = Metaspaceカテゴリのメモリ使用量(=Class カテゴリ内のMetadata内訳) + Class カテゴリのメモリ使用量。


カテゴリ別チューニングオプション

NMT カテゴリに関連する JVM オプションには以下がある。

カテゴリ 説明
Java Heap -Xms<size> -Xmx<size>
Class -XX:CompressedClassSpaceSize=<size>
Thread -Xss<size> –XX:ThreadStackSize=<size>
Code -XX:InitialCodeCacheSize=<size> -XX:ReservedCodeCacheSize=<size>
GC -XX:+UseSerialGC -XX:+UserG1GC
Symbol -XX:StringTableSize=<N>
Shared class space -Xshare:off
Metaspace -XX:MetaspaceSize=<size> -XX:MaxMetaspaceSize=<size>

MetaspaceSize は、旧来のPermGen。 MetaspaceSize の中身は、Class Space とそれ以外(Metadata)の領域に分かれており、Class Space のサイズを規定するものが CompressedClassSpace となる。


ベースラインからの差分

ある時点の値をベースラインとして、ベースラインとの差分を表示することができる。

jcmd <pid> VM.native_memory baseline scale=MB

jcmd <pid> VM.native_memory detail.diff
jcmd <pid> VM.native_memory summary.diff scale=MB

メモリリークの調査は、このコマンドを使うことになる。

+ - でベースラインとの差分が合わせて表示される。

jcmd 18628 VM.native_memory summary.diff
18628:

Native Memory Tracking:

(Omitting categories weighting less than 1KB)

Total: reserved=5517979KB -97KB, committed=87535KB -97KB

malloc=15887KB -97KB #107308 +12
...


NMT jcmd オプション

jcmdを使用して収集したデータをダンプし、必要に応じて、そのデータを最後のベースラインと比較する。

jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]

オプションの説明は以下。

オプション 説明
summary カテゴリ別に集約されたサマリーを出力する
detail カテゴリ別に集約されたメモリー使用量、仮想メモリー・マップ、コール・サイト別に集約されたメモリー使用量を出力する
baseline 比較のために新しいメモリー使用量スナップショットを作成する
summary.diff 最後のベースラインに照らして新しいサマリー・レポートを出力する
detail.diff 最後のベースラインに照らして新しい詳細レポートを出力する
shutdown NMTを停止する






以上の内容はhttps://blog1.mammb.com/entry/2026/02/25/200910より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14