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.
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 KotlinCompileDaemonjinfo
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 -Xmx1gPrinting 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
testjvisualvm
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=detailRunning 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 helpThe 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.
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
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.