Using JDK Built‑in Tools to Monitor and Diagnose Java Applications
This article demonstrates how to use the JDK's built-in command-line and graphical tools—such as jps, jinfo, jvisualvm, jstat, jstack, and jcmd—to monitor JVM performance, analyze GC behavior, inspect thread stacks, and troubleshoot memory and configuration issues in Java applications.
Hello everyone, I am Chen. You may initially feel intimidated by complex troubleshooting tools, but as you gain experience with Java programs and frameworks, these tools become increasingly handy.
This article introduces how to use the JDK's built‑in tools to analyze and locate problems in Java applications.
Using JDK Built‑in Tools to View JVM Information
The JDK ships with many command‑line and GUI utilities that help you inspect JVM details. For example, on my machine the ls command lists a large number of tools provided by JDK 8.
The following diagram shows the basic purpose of each tool.
To test the tools, we first create a program that starts ten threads, each allocating roughly a 10 MB string and then sleeping for ten seconds, thereby putting pressure on the GC.
// Start 10 threads
IntStream.rangeClosed(1, 10).mapToObj(i -> new Thread(() -> {
while (true) {
// Each thread loops forever, sleeps 10 s, prints 10 M data
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 modify pom.xml to set the main class for the Spring‑Boot Maven plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication</mainClass>
</configuration>
</plugin>We launch the program with java -jar and set both the minimum and maximum heap size to 1 GB:
java -jar common-mistakes-0.0.1-SNAPSHOT.jar -Xms1g -Xmx1gjps
First, jps lists Java processes, which is more convenient than using ps :
➜ ~ jps
12707
22261 Launcher
23864 common-mistakes-0.0.1-SNAPSHOT.jar
15608 RemoteMavenServer36
23243 Main
23868 Jps
22893 KotlinCompileDaemonjinfo
Next, jinfo prints the JVM's system properties and flags, revealing that the -Xms1g and -Xmx1g options were mistakenly passed as program arguments instead of JVM options, resulting in a default max heap of about 4 GB.
➜ ~ jinfo 23864
Java System Properties:
... (output omitted for brevity) ...
VM Flags:
-XX:CICompilerCount=4 -XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 ... -XX:+UseG1GC
VM Arguments:
java_command: common-mistakes-0.0.1-SNAPSHOT.jar -Xms1g -Xmx1gPrinting the VM and program arguments from within the code confirms the correct configuration after moving the options before -jar :
➜ target git:(master) ✗ java -Xms1g -Xmx1g -jar common-mistakes-0.0.1-SNAPSHOT.jar test
VM options
-Xms1g
-Xmx1g
Program arguments
testjvisualvm
We then open the heavyweight GUI tool jvisualvm to verify that the JVM parameters have taken effect and to observe GC activity, heap usage (250 MB–900 MB), and the number of active threads (22). The tool also allows manual GC and heap dump operations.
jconsole
For a more compact graphical view, jconsole can display GC curves and other MBean attributes.
jstat
On headless Linux servers, the command‑line tool jstat can output periodic GC and memory statistics. Using -gcutil every five seconds for 100 iterations 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
... (additional rows omitted) ...S0 – Survivor0, S1 – Survivor1, E – Eden, O – Old generation, M – Metaspace, YGC – Young GC count, YGCT – Young GC time, FGC – Full GC count, FGCT – Full GC time.
Thread panels in jvisualvm show that most threads are sleeping for ten seconds, matching the program logic.
Clicking the "Thread Dump" button displays a snapshot of thread stacks.
jstack
The command‑line tool jstack can also capture thread dumps:
➜ ~ jstack 23940
Full thread dump Java HotSpot 64‑Bit Server VM (11.0.3+12‑LTS mixed mode):
... (output omitted) ...
"main" #1 prio=5 os_prio=31 cpu=440.66ms elapsed=574.86s ...
"Thread-1" #13 prio=5 os_prio=31 cpu=17851.77ms elapsed=574.41s ...The dump can be analyzed with online tools such as fastthread .
jcmd
Finally, we explore the Native Memory Tracking (NMT) feature of the HotSpot VM. Enabling it with -XX:NativeMemoryTracking=detail allows jcmd to report fine‑grained memory usage.
-Xms1g -Xmx1g -XX:ThreadStackSize=256k -XX:NativeMemoryTracking=detailRunning jcmd 24404 VM.native_memory summary shows that 32 threads collectively reserve about 4 GB of stack memory, which is unexpected because the intended stack size is only 256 KB.
➜ ~ jcmd 24404 VM.native_memory summary
Native Memory Tracking:
Total: reserved=6635310KB, committed=5337110KB
- Thread (reserved=4209797KB, committed=4209797KB) (thread #32)
(stack: reserved=4209664KB, committed=4209664KB)The issue stems from using the suffix k (which denotes kilobytes) when the option expects a plain number; the correct value should be 256 , not 256k . After fixing the parameter and rerunning jcmd , the reported stack size matches the expectation.
Beyond NMT, jcmd offers many other commands; jcmd 24781 help lists them all.
jcmd 24781 helpIn addition to the tools covered above, the JDK includes several other utilities documented in the official JDK tools guide.
Official documentation: https://docs.oracle.com/javase/8/docs/technotes/tools/
Backend‑specific technical community
We are building a high‑quality technical exchange community. Developers, recruiters, and anyone interested in sharing job referrals are welcome to join and help each other grow.
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.