Operations 15 min read

Using JDK Built‑in Tools to Monitor and Diagnose the JVM

This article demonstrates how to use the JDK’s native command‑line and graphical utilities—such as jps, jinfo, jvisualvm, jconsole, jstat, jstack and jcmd—to observe JVM metrics, troubleshoot memory and thread issues, and verify JVM parameters in Java applications.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Using JDK Built‑in Tools to Monitor and Diagnose the JVM

Many developers feel uneasy about using complex tools to diagnose Java applications, but once you become familiar with the JDK’s built‑in utilities, they become indispensable for monitoring JVM behavior.

Using JDK Tools to View JVM State

The JDK ships with numerous command‑line and GUI tools. Running ls on a JDK 8 installation shows a long list of utilities.

Below is a quick overview of the most common tools:

To illustrate these tools, we first create a test program that starts ten threads, each allocating roughly 10 MB of a string and then sleeping for ten seconds, putting pressure on the GC.

IntStream.rangeClosed(1, 10).mapToObj(i -> new Thread(() -> {
    while (true) {
        String payload = IntStream.rangeClosed(1, 10000000)
                .mapToObj(__ -> "a")
                .collect(Collectors.joining("")) + UUID.randomUUID().toString();
        try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println(payload.length());
    }
})).forEach(Thread::start);
TimeUnit.HOURS.sleep(1);

We then configure spring-boot-maven-plugin to set the main class and launch the jar with -Xms1g -Xmx1g JVM options.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <mainClass>org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication</mainClass>
    </configuration>
</plugin>

jps

Use jps to list Java processes, which is more convenient than ps :

➜ ~ jps
12707
22261 Launcher
23864 common-mistakes-0.0.1-SNAPSHOT.jar
15608 RemoteMavenServer36
23243 Main
23868 Jps
22893 KotlinCompileDaemon

jinfo

jinfo prints JVM system properties and flags, revealing that the -Xms1g and -Xmx1g options were mistakenly passed as program arguments rather than JVM options.

➜ ~ jinfo 23864
Java System Properties:
... user.name=zhuye ...
VM Flags:
-XX:CICompilerCount=4 -XX:ConcGCThreads=2 ... -XX:+UseG1GC
VM Arguments:
java_command: common-mistakes-0.0.1-SNAPSHOT.jar -Xms1g -Xmx1g

Printing the arguments from within the program confirms the correct configuration after moving the options before -jar :

➜ target ✗ java -Xms1g -Xmx1g -jar common-mistakes-0.0.1-SNAPSHOT.jar test
VM options
-Xms1g
-Xmx1g
Program arguments
test

jvisualvm

Launch the heavyweight GUI tool jvisualvm to verify that the JVM parameters are applied and to observe GC activity, heap usage (250 MB–900 MB), and thread count (22). The tool also allows manual GC and heap dumps.

jconsole

jconsole provides chart‑based monitoring of memory pools and other MBean attributes, offering a more convenient visual view than command‑line tools.

jstat

When a GUI is unavailable, jstat -gcutil can output GC and memory statistics at a fixed interval. Sample output shows frequent Young GC and a Full GC roughly every ten seconds.

➜ ~ jstat -gcutil 23940 5000 100
 S0   S1    E    O    M   CCS   YGC   YGCT   FGC   FGCT   CGC   CGCT   GCT
0.00 100.00 0.36 87.63 94.30 81.06 539 14.021 33 3.972 837 0.976 18.968
...
S0 – Survivor0, S1 – Survivor1, E – Eden, O – Old, M – Metaspace, YGC – Young GC count, YGCT – Young GC time, FGC – Full GC count, FGCT – Full GC time.

jstack

jstack captures thread dumps. The output shows many threads sleeping for ten seconds, matching the test program’s logic. The dump can be analyzed with online tools such as fastthread .

➜ ~ jstack 23940
Full thread dump Java HotSpot 64‑Bit Server VM (11.0.3+12‑LTS mixed mode):
"main" #1 prio=5 os_prio=31 cpu=440.66ms elapsed=574.86s tid=0x00007ffdd9800000 nid=0x2803 waiting on condition ...
...

jcmd

The jcmd utility can query Native Memory Tracking (NMT). Enabling -XX:NativeMemoryTracking=detail and running jcmd <pid> VM.native_memory summary reveals that 32 threads reserve about 4 GB of stack memory because the -XX:ThreadStackSize flag was incorrectly specified with a trailing “k”. Correcting it to -XX:ThreadStackSize=256 reduces the reserved memory to the expected size.

-Xms1g -Xmx1g -XX:ThreadStackSize=256k -XX:NativeMemoryTracking=detail

Running jcmd <pid> VM.native_memory detail after the fix shows each thread using a 256 KB stack instead of 256 MB.

Beyond NMT, jcmd help lists many other diagnostic commands.

jcmd 24781 help

The JDK also includes additional tools documented in the official Oracle guide.

Official documentation: https://docs.oracle.com/javase/8/docs/technotes/tools/

Source: https://time.geekbang.org/column/article/224816

Final Note (Support the Author)

The author offers PDF collections of three columns (Spring Cloud, Spring Boot, Mybatis) via the “码猿技术专栏” WeChat public account. If this article helped you, please like, share, and follow the account for more technical content.

JavaJVMMonitoringperformanceJDKTroubleshooting
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.