On this page
jcmd, jmap & jstack
The JDK ships with command-line diagnostic tools for inspecting running JVM processes — essential for troubleshooting production issues.
jps — List Java Processes
jps # list running Java processes
jps -l # show full main class / JAR name
jps -v # show JVM arguments
jps -m # show main method arguments
Output:
12345 MyApplication
67890 org.apache.catalina.startup.Bootstrap
jcmd — Swiss Army Knife
The primary diagnostic tool (Java 7+). Send commands to a running JVM:
jcmd # list all Java processes
jcmd 12345 help # available commands for this process
jcmd 12345 VM.flags # show JVM flags
jcmd 12345 VM.system_properties # system properties
jcmd 12345 VM.command_line # full command line
jcmd 12345 GC.heap_info # heap configuration
jcmd 12345 GC.class_histogram # object count by class
jcmd 12345 Thread.print # thread dump (same as jstack)
jcmd 12345 JFR.start duration=60s filename=recording.jfr
Generate Heap Dump
jcmd 12345 GC.heap_dump /tmp/heap.hprof
Run GC
jcmd 12345 GC.run
jmap — Memory Map
# Heap summary
jmap -heap 12345
# Histogram of objects on heap
jmap -histo 12345
jmap -histo:live 12345 # after full GC — only live objects
# Generate heap dump
jmap -dump:live,format=b,file=/tmp/heap.hprof 12345
Sample histogram output:
num #instances #bytes classname
-------------------------------------------------------
1: 500000 12000000 java.lang.String
2: 100000 8000000 java.util.HashMap$Node
3: 50000 4000000 com.example.User
jstack — Thread Dump
Captures the state of all threads — essential for diagnosing deadlocks and performance issues:
jstack 12345 > /tmp/threaddump.txt
jstack -l 12345 # with lock info
Sample output:
"main" #1 prio=5 os_prio=0 tid=0x00007f8a1c00a000 nid=0x1234 runnable
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.example.Client.readResponse(Client.java:45)
"pool-1-thread-1" #12 prio=5 os_prio=0 tid=0x00007f8a1c012800 nid=0x5678 waiting on condition
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
Detecting Deadlocks
jstack 12345 | grep -A 20 "Found one Java-level deadlock"
jstack automatically reports deadlocks at the end of the dump.
Typical Troubleshooting Workflow
1. jps -l → find process ID
2. jcmd <pid> VM.flags → check JVM configuration
3. jcmd <pid> GC.heap_info → check heap usage
4. jmap -histo:live <pid> → find memory hogs
5. jstack <pid> → check for deadlocks / blocked threads
6. jcmd <pid> GC.heap_dump → capture heap for analysis (if OOM)
Analyzing Heap Dumps
Open .hprof files with:
- Eclipse MAT (Memory Analyzer Tool) — recommended
- VisualVM
- IntelliJ IDEA — built-in profiler
Look for:
- Large collections (
HashMap,ArrayList) retaining too many objects - Class loader leaks
- Unclosed connections or streams
Best Practices
- Capture thread dumps before restarting a hung application
- Take heap dumps during low-traffic periods — dumps pause the JVM
- Use
jcmdas the primary tool — it is safer thanjmapon production (less pause time) - Automate periodic thread dump capture for intermittent issues
- Always note the PID and timestamp when saving diagnostic output