How to create a class histogram of a JVM app from the very same JVM app?
Asked Answered
T

1

2

I would like to diagnose some unexpected OOM errors using jmap or jcmd. Unfortunately, these tools are not easy to use in a CI pipeline, because I would have to launch the JVM app in the background, somehow get its PID, and then get the timing right for the results to be useful.

So I tried to launch them from the JVM app that is to be diagnosed itself — a programmatic selfie.

At the appropriate place in code, I launch jmap or jcmd as a new process:

val process = ProcessBuilder("jcmd", getPID(), "GC.class_histogram")
    .redirectOutput(ProcessBuilder.Redirect.PIPE)
    .redirectError(ProcessBuilder.Redirect.PIPE)
    .start()

process.waitFor(2, TimeUnit.MINUTES)

Unfortunately, this code hangs for both tools. The system monitor says that both the JVM app and the jcmd are sleeping. However, when I use the jcmd on the sleeping JVM:

jcmd 37058 GC.class_histogram

I get the desired histogram immediately.

Any idea what is going on?

Td answered 8/8, 2022 at 0:38 Comment(0)
P
8

You can get a histogram right from a Java application even without starting a separate process:

String histogram = (String) ManagementFactory.getPlatformMBeanServer().invoke(
        new ObjectName("com.sun.management:type=DiagnosticCommand"),
        "gcClassHistogram",
        new Object[]{null},
        new String[]{"[Ljava.lang.String;"});
System.out.println(histogram);
Pennywise answered 8/8, 2022 at 6:7 Comment(1)
This works! Java 17 and Java 21. Thanks a bunch.Stadium

© 2022 - 2024 — McMap. All rights reserved.