The jcmd tool sends diagnostic command requests to a running Java Virtual Machine (JVM). It is part of the jdk.jcmd module and provides a comprehensive way to interact with and diagnose running Java processes.
Basic Usage
jcmd <pid | main-class> <command> [arguments]
jcmd -l
Source Code
The jcmd implementation is located at:
- Main class:
src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java:1
- Arguments:
src/jdk.jcmd/share/classes/sun/tools/jcmd/Arguments.java:1
- Process matcher:
src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java:1
Command Syntax
List Processes
Send Command
Get Help
List all running Java processes:Output:12345 com.example.MyApplication
12346 org.apache.catalina.startup.Bootstrap
12347 jdk.jcmd/sun.tools.jcmd.JCmd -l
Send a diagnostic command to a specific process:# By process ID
jcmd 12345 VM.version
# By main class name
jcmd MyApplication VM.version
# To all Java processes (use with caution)
jcmd 0 VM.version
Get list of available commands:Get help for specific command:
Options
List all running Java processes with their process IDs and main class names.
Display help message. Can also use -? or --help.
Read commands from a file and execute them on the specified process.jcmd <pid> -f commands.txt
Example commands.txt:VM.version
VM.flags
Thread.print
Display the performance counters exposed by the JVM process.jcmd <pid> PerfCounter.print
Common Diagnostic Commands
VM.version
VM.flags
VM.system_properties
VM.command_line
VM.uptime
Display JVM version information:Example output:OpenJDK 64-Bit Server VM version 21.0.1+12
JDK 21.0.1
Print all VM flags (both default and modified):# All flags
jcmd <pid> VM.flags
# Only non-default flags
jcmd <pid> VM.flags -all
Print all system properties:jcmd <pid> VM.system_properties
Print the command line used to start the JVM:jcmd <pid> VM.command_line
Print VM uptime:Example output:
Thread Diagnostics
Thread.print
Thread.dump_to_file
Print all thread stack traces:jcmd <pid> Thread.print
# With lock information
jcmd <pid> Thread.print -l
Dump thread information to a file:jcmd <pid> Thread.dump_to_file /tmp/thread-dump.txt
Heap and GC Diagnostics
GC.heap_info
GC.class_histogram
GC.heap_dump
GC.run
GC.finalizer_info
Display heap information: Display histogram of Java object heap:# Live objects only
jcmd <pid> GC.class_histogram
# All objects
jcmd <pid> GC.class_histogram -all
Generate a heap dump:jcmd <pid> GC.heap_dump /tmp/heap-dump.hprof
# Live objects only
jcmd <pid> GC.heap_dump -live /tmp/heap-dump-live.hprof
Request garbage collection: Display information about objects awaiting finalization:jcmd <pid> GC.finalizer_info
VM.class_hierarchy
VM.classloader_stats
VM.classloaders
Display class hierarchy:# All classes
jcmd <pid> VM.class_hierarchy
# Specific class and subclasses
jcmd <pid> VM.class_hierarchy -s java.lang.Thread
Display classloader statistics:jcmd <pid> VM.classloader_stats
Print all classloaders:jcmd <pid> VM.classloaders
Compiler.codecache
Compiler.codelist
JFR Commands
Display code cache information:jcmd <pid> Compiler.codecache
Display compiled methods:jcmd <pid> Compiler.codelist
Java Flight Recorder commands:# Start recording
jcmd <pid> JFR.start name=MyRecording duration=60s filename=/tmp/recording.jfr
# Check recording status
jcmd <pid> JFR.check
# Dump recording
jcmd <pid> JFR.dump name=MyRecording filename=/tmp/dump.jfr
# Stop recording
jcmd <pid> JFR.stop name=MyRecording
Native Memory Tracking
Native Memory Tracking must be enabled at JVM startup with -XX:NativeMemoryTracking=summary or -XX:NativeMemoryTracking=detail.
Display native memory tracking information:# Summary
jcmd <pid> VM.native_memory summary
# Detailed
jcmd <pid> VM.native_memory detail
# Baseline for comparison
jcmd <pid> VM.native_memory baseline
# Compare with baseline
jcmd <pid> VM.native_memory summary.diff
Usage Examples
Basic Diagnostics Workflow
# 1. List all Java processes
jcmd -l
# 2. Get available commands for a process
jcmd 12345 help
# 3. Check VM info
jcmd 12345 VM.version
jcmd 12345 VM.flags
jcmd 12345 VM.uptime
# 4. Check system properties
jcmd 12345 VM.system_properties | grep java.home
Thread Analysis
# Get thread dump
jcmd 12345 Thread.print > thread-dump.txt
# Get thread dump with lock info
jcmd 12345 Thread.print -l > thread-dump-locks.txt
# Continuous monitoring (every 5 seconds, 10 times)
for i in {1..10}; do
echo "=== Dump $i ==="
jcmd 12345 Thread.print
sleep 5
done
Memory Analysis
# Check heap information
jcmd 12345 GC.heap_info
# Get class histogram (top memory consumers)
jcmd 12345 GC.class_histogram | head -20
# Generate heap dump for analysis
jcmd 12345 GC.heap_dump /tmp/heap-$(date +%Y%m%d-%H%M%S).hprof
# Check native memory (if NMT enabled)
jcmd 12345 VM.native_memory summary
# Start JFR recording for 60 seconds
jcmd 12345 JFR.start name=perf duration=60s filename=/tmp/perf.jfr
# Monitor GC activity
jcmd 12345 GC.heap_info
jcmd 12345 GC.run
jcmd 12345 GC.heap_info
# Check compiler activity
jcmd 12345 Compiler.codecache
Batch Commands from File
# Create commands file
cat > diagnostic-commands.txt << 'EOF'
VM.version
VM.uptime
GC.heap_info
Thread.print
EOF
# Execute all commands
jcmd 12345 -f diagnostic-commands.txt > diagnostics.log
Emergency Diagnostics
#!/bin/bash
# Quick diagnostic script for troubled application
PID=$1
OUTDIR="diagnostics-$(date +%Y%m%d-%H%M%S)"
mkdir -p $OUTDIR
echo "Gathering diagnostics for PID $PID..."
jcmd $PID VM.version > $OUTDIR/vm-version.txt
jcmd $PID VM.flags > $OUTDIR/vm-flags.txt
jcmd $PID VM.system_properties > $OUTDIR/system-properties.txt
jcmd $PID Thread.print -l > $OUTDIR/thread-dump.txt
jcmd $PID GC.heap_info > $OUTDIR/heap-info.txt
jcmd $PID GC.class_histogram > $OUTDIR/class-histogram.txt
jcmd $PID VM.native_memory summary > $OUTDIR/native-memory.txt 2>/dev/null
jcmd $PID PerfCounter.print > $OUTDIR/perf-counters.txt
echo "Diagnostics saved to $OUTDIR/"
Process Selection
The process identifier can be:
By PID
By Main Class
All Processes
Full or partial main class name:# Full class name
jcmd com.example.MyApplication VM.version
# Partial match
jcmd MyApplication VM.version
Send command to all Java processes (use PID 0):Use with caution - this affects all running Java processes!
The jdk.jcmd module also includes other diagnostic tools:
- jinfo -
src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java:1 - Display Java configuration information
- jmap -
src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java:1 - Memory map for Java processes
- jps -
src/jdk.jcmd/share/classes/sun/tools/jps/Jps.java:1 - List instrumented JVMs
- jstack -
src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java:1 - Print Java stack traces
- jstat -
src/jdk.jcmd/share/classes/sun/tools/jstat/ - JVM statistics monitoring tool
jcmd is the recommended tool for diagnostics as it provides the most comprehensive set of commands and is actively maintained. Many functions of the older tools (jinfo, jmap, jstack) can be performed using jcmd.
Implementation Details
The jcmd tool works by:
- Process Discovery: Uses the Attach API to find running JVMs
- Command Transmission: Attaches to the target JVM via
VirtualMachine.attach()
- Command Execution: Sends diagnostic commands through
HotSpotVirtualMachine.executeJCmd()
- Response Handling: Receives and displays output from the JVM
Source: src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java:110-131
Exit Codes
0: Command executed successfully
1: Error occurred during execution
Troubleshooting
Permission Denied
Process Not Found
Command Not Recognized
If you get permission errors:# Run as the same user as the target JVM
sudo -u appuser jcmd <pid> <command>
If jcmd can’t find the process:# Verify process is running
jcmd -l
ps aux | grep java
# Check if Attach API is available
jps -v
If a command is not recognized:# List all available commands
jcmd <pid> help
# Some commands require specific JVM flags
# For example, NMT requires -XX:NativeMemoryTracking
See Also