Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monitoring java native memory

We are monitoring jvm metrics like heap, metaspace, threads and gc count and we are able to push these metrics to monitorng server like prometheus. Similarly we wanted to track Java native memory metrics(output of jcmd VM.sumary). My question is, is it possible to get these metrics by calling any jvm runtime classes?

like image 798
Uday Shankar Avatar asked Aug 12 '19 03:08

Uday Shankar


3 Answers

Yes, it is possible to get NativeMemoryTracking summary directly from a Java application:

import javax.management.JMException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

public class DiagnosticCommand {

    public static String execute(String command, String... args) throws JMException {
        return (String) ManagementFactory.getPlatformMBeanServer().invoke(
                new ObjectName("com.sun.management:type=DiagnosticCommand"),
                command,
                new Object[]{args},
                new String[]{"[Ljava.lang.String;"});
    }

    public static void main(String[] args) throws Exception {
        String summary = DiagnosticCommand.execute("vmNativeMemory", "summary");
        System.out.println(summary);
    }
}

You'll have to parse the text output though.

Note that the most important parts of the NMT report can be tracked separately with the designated MBeans, including

  • Java Heap
  • Code Cache
  • Metaspace
  • Compressed Class Space
  • Direct Byte Buffers and Mapped Byte Buffers

See MemoryPoolMXBean and BufferPoolMXBean.

As I told in the comments, monitoring NMT output is not always helpful in practice, since it does not directly reflect the actual physical memory used by the process. NMT can report much less memory than the actual usage, or it can also report more memory than the process consumes from the OS perspective.

Since NMT can miss the large amount of OS memory consumed by a Java process, it's also useful to monitor the process' resident set size (RSS). On Linux this can be done by parsing /proc/[pid]/stat or /proc/[pid]/status.

like image 192
apangin Avatar answered Sep 18 '22 21:09

apangin


I don't think there's a Java API for that. Your best bet might be to invoke the jcmd <PID> VM.native_memory command and parse its output. Of course, you need to enable native memory tracking for your process first.

like image 23
Juraj Martinka Avatar answered Sep 20 '22 21:09

Juraj Martinka


You can find many things you want in JMX. One of the answers to question "Why Use JMX Technology?" is "Monitor and manage the Java VM". In Oracle doc:

The Java Virtual Machine (Java VM) is highly instrumented using the JMX technology. You can start a JMX agent to access the built-in Java VM instrumentation, and thereby monitor and manage a Java VM remotely.

//Metaspace
for (MemoryPoolMXBean memoryMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
    if ("Metaspace".equals(memoryMXBean.getName())) {
            System.out.println(memoryMXBean.getUsage().getUsed());
            System.out.println(memoryMXBean.getUsage().getCommitted());
            System.out.println(memoryMXBean.getUsage().getMax());
            System.out.println(memoryMXBean.getUsage().getInit());
    }
}

//current number of live threads including both daemon and non-daemon threads
int threadCount = ManagementFactory.getThreadMXBean().getThreadCount();

//Returns the current memory usage of the heap and non-heap
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapMemory = memoryMXBean.getHeapMemoryUsage();
MemoryUsage nonHeapMemory = memoryMXBean.getNonHeapMemoryUsage();

//GarbageCollector total number of collections
List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
long totalCollectionCount = garbageCollectorMXBeans.stream().mapToLong(x -> x.getCollectionCount()).sum();
like image 22
Turac Avatar answered Sep 18 '22 21:09

Turac