Skip to main content
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 all running Java processes:
jcmd -l
# or
jcmd
Output:
12345 com.example.MyApplication
12346 org.apache.catalina.startup.Bootstrap
12347 jdk.jcmd/sun.tools.jcmd.JCmd -l

Options

-l
none
List all running Java processes with their process IDs and main class names.
jcmd -l
-h
none
Display help message. Can also use -? or --help.
jcmd -h
-f
file
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
PerfCounter.print
none
Display the performance counters exposed by the JVM process.
jcmd <pid> PerfCounter.print

Common Diagnostic Commands

VM Information

Display JVM version information:
jcmd <pid> VM.version
Example output:
OpenJDK 64-Bit Server VM version 21.0.1+12
JDK 21.0.1

Thread Diagnostics

Print all thread stack traces:
jcmd <pid> Thread.print

# With lock information
jcmd <pid> Thread.print -l

Heap and GC Diagnostics

Display heap information:
jcmd <pid> GC.heap_info

Class and Classloader Information

Display class hierarchy:
# All classes
jcmd <pid> VM.class_hierarchy

# Specific class and subclasses
jcmd <pid> VM.class_hierarchy -s java.lang.Thread

Performance and Profiling

Display code cache information:
jcmd <pid> Compiler.codecache

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

Performance Monitoring

# 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:
Exact process ID:
jcmd 12345 VM.version
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:
  1. Process Discovery: Uses the Attach API to find running JVMs
  2. Command Transmission: Attaches to the target JVM via VirtualMachine.attach()
  3. Command Execution: Sends diagnostic commands through HotSpotVirtualMachine.executeJCmd()
  4. 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

If you get permission errors:
# Run as the same user as the target JVM
sudo -u appuser jcmd <pid> <command>

See Also

Build docs developers (and LLMs) love