JVM has multiple internal memory regions. Native Memory Tracking (NMT) helps Java developers to identify memory leaks, excessive memory usage, and other related issues on these internal memory regions by providing detailed information on each memory region. In this post, let’s learn how to use NMT to troubleshoot JVM memory related problems.

Video

In this video, let’s learn how to use NMT to troubleshoot JVM memory related problems.

What is Native Memory Tracking (NMT)?

JVM Memory Regions
Fig: JVM Memory Regions

JVM Memory has following internal regions:

  1. Heap Memory (Young Generation, Old Generation)
  2. Metaspace
  3. Threads
  4. Code Cache
  5. Direct Buffer
  6. GC
  7. JNI
  8. NMT
  9. Misc

If you are interested, you can watch this video clip to learn more about these JVM internal memory regions.

NMT is a feature of the Java Virtual Machine (JVM) that tracks and reports all the JVM memory regions usage.

Benefits of Using NMT

NMT is primarily used to identify memory leaks in the native memory regions. By analyzing NMT data, we can isolate which region in the native memory is always growing and not getting freed up. It would facilitate isolating the root cause of OutOfMemoryError.

What is the difference between Garbage Collection Log and NMT?

Garbage Collection logs contain finest details about the Java Heap space (i.e. Young Generation, Old Generation) and Metaspace usage and garbage collection metrics (at what time it ran, like how long each GC event ran, how much memory recovered after each GC event…). However, it doesn’t contain details about the native memory regions. 

On the other hand, NMT contains details only about native memory regions size.

When to use Garbage Collection Log and NMT?

If you are trying to optimize Garbage Collection performance or troubleshoot memory leak in the Java Heap space or Metaspace, then you need to use GC Log. 

If you are trying to isolate memory leaks in native memory regions, then you need to use NMT data.

How to Enable NMT

NMT is not enabled by default in the JVM, so you need to explicitly turn it on. You can enable NMT by passing the -XX:NativeMemoryTracking option to the JVM with either the summary or detail level. The summary level provides a high-level overview, while the detail level offers more granular information.

java -XX:NativeMemoryTracking=summary -jar YourApplication.jar

or for detailed tracking:

java -XX:NativeMemoryTracking=detail -jar YourApplication.jar

Capture NMT Data

Once NMT is enabled, you can capture and analyze the native memory usage data in several ways:

1. Using jcmd

The jcmd utility is a powerful tool that comes with the JDK. You can use it to request various diagnostics from a running JVM, including NMT statistics.

jcmd <pid> VM.native_memory summary > nmt_report.txt

or for detailed information:

jcmd <pid> VM.native_memory detail > nmt_report.txt

Replace <pid> with the process ID of your running Java application.

2. Periodically Capturing Data

For long-running applications, it might be useful to capture NMT data periodically. This can be achieved by setting up a cron job or a scheduled task that runs the jcmd command at regular intervals.

Analyze NMT using GCeasy

While NMT provides valuable insights, analyzing raw NMT data can be complex and time-consuming. This is where GCeasy comes into play. GCeasy is a powerful tool that simplifies the analysis of JVM memory reports, including NMT reports. It provides a user-friendly interface and detailed visualizations to help you understand memory usage patterns and identify potential issues.

Steps to Analyze NMT Reports with GCeasy

1. Upload NMT file to GCeasy: Go to the GCeasy website and upload the captured NMT file.

Uploading NMT Data to GCeasy
Fig: Uploading NMT Data to GCeasy

2. Analyze the Report: GCeasy will parse the NMT file and present the data in an easy-to-understand format. You will see visualizations and detailed breakdowns of memory usage across different components like Java Heap, Class, Thread, Code, and GC.

Memory Regions report generated by GCeasy
Fig: Memory Regions report generated by GCeasy

3. JVM Memory Regions Trend: GCeasy presents you with the trending report of each JVM memory region as well. In this section, for each memory region following data will be reported:

  • Reserved size is the total amount of memory that the JVM has reserved from the operating system. 
  • Committed size refers to the amount of memory that the JVM has allocated from the operating system and is currently using. 
Memory Trends report generated by GCeasy by parsing NMT data
Fig: Memory Trends report generated by GCeasy by parsing NMT data

4. Identify Issues: By analyzing the trends in committed and reserved size, you can identify patterns and potential issues. For instance, a steady increase in committed memory might indicate a memory leak, while significant fluctuations in reserved memory could suggest that the JVM is frequently resizing its memory pools. Monitoring these trends helps maintain optimal performance and stability of your application. For example: If you observe the below image, GCeasy is highlighting the issues in the Native Memory Tracking report.

GCeasy highlighting Issues in Native Memory Tracking Report
Fig: GCeasy highlighting Issues in Native Memory Tracking Report

Also read: The 7 most important JVM arguments that you can pass to JVM around Garbage collection and memory to make your application more effective.

Conclusion

Native Memory Tracking (NMT) is an extremely light-weight artifact that you can use to detect and address memory leaks and inefficiencies across various memory regions. Tools like GCeasy further streamline this process, transforming raw NMT data into actionable insights through user-friendly visualizations. Regular monitoring with NMT not only aids in quick troubleshooting but also ensures your application runs optimally, providing a robust foundation for sustained performance improvements.