ネイティブ・イメージでのネイティブ・メモリー・トラッキング(NMT)
ネイティブ・メモリー・トラッキング(NMT)は、アプリケーションのオフヒープ・メモリー使用量を記録する保守性機能です。「オフヒープ・メモリー」という用語は、「ネイティブ・メモリー」または「管理対象外メモリー」と同じ意味で使用されることがあります。これは基本的に、ガベージ・コレクタによって管理されていないメモリーを意味します。
HotSpot JVMとは異なり、ネイティブ・イメージは、そのガベージ・コレクタによって管理される収集済ヒープのメモリーを主に使用します。ただし、管理対象ヒープへの割当てを回避するためにネイティブ・イメージによってネイティブ・メモリーが使用される場所は依然として多くあります。いくつかの例として、JFR、ガベージ・コレクタ、ヒープ・ダンプなどがあります。ネイティブ・メモリーは、Unsafe#allocateMemory(long)
を使用してアプリケーション・レベルで直接リクエストすることもできます。
ネイティブ・メモリー・トラッキングの有効化
NMTサポートはデフォルトで無効になっており、ビルド時に明示的に有効にする必要があります。
NMTを使用してネイティブ実行可能ファイルをビルドするには、--enable-monitoring=nmt
オプションを使用します。NMTは、ビルド時に含まれる場合、実行時に常に有効になります。これは、実行時にNMTを有効または無効にできるHotSpotとは異なります。
native-image --enable-monitoring=nmt YourApplication
ネイティブ実行可能ファイルからアプリケーションを起動するときに-XX:+PrintNMTStatistics
を追加すると、アプリケーションの完了時にレポートを標準出力に書き込むようにNMTに指示されます。
./yourapplication -XX:+PrintNMTStatistics
パフォーマンス
ネイティブ・イメージでは、NMTのCPUとメモリーの消費量が非常に少なくなります。JFRなどの他の保守性機能と比較して、NMTのオーバーヘッドは相対的に非常に少なくなります。
NMTのJFRイベント
OpenJDK JFRイベントのjdk.NativeMemoryUsage
およびjdk.NativeMemoryUsageTotal
は、ネイティブ・イメージでサポートされています。
アクセス可能な2つのネイティブ・イメージ固有のJFRイベント(jdk.NativeMemoryUsagePeak
およびjdk.NativeMemoryUsageTotalPeak
)もあります。これらのネイティブ・イメージ固有のイベントは、OpenJDKから移植されたJFRイベントを介しては公開されていないピーク使用量データを公開するために作成されています。これらの新しいイベントは、試験段階としてマークされています。場合によっては、JDK Mission Controlなどのソフトウェアで試験段階のイベントを表示するために、それらのイベントを有効にする必要があります。
NMTでこれらのJFRイベントを使用するには、native-image
ツールの起動時に--enable-monitoring=jfr,nmt
オプションを渡してJFRモニタリングを有効にしてから、実行時にJFR記録を開始します。(詳細は、「ネイティブ・イメージでのJDK Flight Recorder (JFR)」を参照してください)。
次に、jfr
コマンドライン・ツールを使用して表示した場合の新しいイベントの例を示します:
jfr print --events jdk.NativeMemoryUsagePeak recording.jfr
jdk.NativeMemoryUsagePeak {
startTime = 13:18:50.605 (2024-04-30)
type = "Threading"
peakReserved = 424 bytes
peakCommitted = 424 bytes
countAtPeak = 4
eventThread = "JFR Shutdown Hook" (javaThreadId = 63)
}
jdk.NativeMemoryUsagePeak {
startTime = 13:18:50.605 (2024-04-30)
type = "Unsafe"
peakReserved = 14.0 kB
peakCommitted = 14.0 kB
countAtPeak = 2
eventThread = "JFR Shutdown Hook" (javaThreadId = 63)
}
制限事項
HotSpotでは、NMTに2つのモード(サマリーと詳細)があります。ネイティブ・イメージでは、現在、NMTサマリー・モードのみがサポートされています。コールサイト・トラッキングを有効にする詳細モードは使用できません。ベースラインの取得もまだ不可能です。これらの追加機能のサポートに関心がある場合は、GitHubのGraalVMプロジェクトにリクエストを提出してください。
mallocトラッキングは、現在使用可能な唯一の機能です(GraalVM for JDK 23の時点)。
ネイティブ・イメージ(HotSpotと同じ)は、VMレベルの割当てと、Unsafe#allocateMemory(long)
で作成された割当てのみをトラッキングできます。たとえば、ライブラリ・コードまたはアプリケーション・コードがmallocを直接コールする場合、そのコールはNMTアカウンティングをバイパスし、トラッキングされません。