ネイティブ・イメージでのネイティブ・メモリー・トラッキング(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アカウンティングをバイパスし、トラッキングされません。

その他の情報