jcmd: The Swiss Army Knife of JVM Diagnostics (Or How to Stop Wondering What Your Java App is…
The Not-So-Secret Weapon That’s Been Hiding in Your JDK Bin Folder All Along
jcmd: The Swiss Army Knife of JVM Diagnostics (Or How to Stop Wondering What Your Java App is Actually Doing)
The Not-So-Secret Weapon That’s Been Hiding in Your JDK Bin Folder All Along

If you’re not a member, click here to read free.
Remember when troubleshooting Java applications meant running seven different tools, opening three monitoring applications, and sacrificing a goat to the JVM gods? Those days are thankfully behind us, thanks to jcmd - the diagnostic tool that decided to be the overachiever in the JDK toolbox.
Think of jcmd as that friend who knows a little bit about everything and can help you fix your car, debug your code, and probably cook a decent meal too. It's the command-line utility that consolidated the functionality of multiple older tools like jstack, jmap, jinfo, and others into one gloriously efficient package.
What Exactly is jcmd?
The jcmd tool is a diagnostic command utility that sends diagnostic command requests to running Java Virtual Machine processes. It's like having a direct hotline to your JVM, allowing you to poke, prod, and interrogate your running Java applications without the need for additional setup or configuration.
The beauty of jcmd lies in its simplicity - it uses the same machine and user credentials as your running JVM, which means no complex authentication or remote connection setup required. It's the lazy developer's dream tool, and I mean that in the best possible way.
Getting Started: The Basics That Actually Matter
Finding Your Java Processes
First things first, you need to find your Java processes. Running jcmd without any arguments (or with -l) lists all running Java processes:
jcmd
# or
jcmd -l
This gives you output like:
23876 sun.tools.jcmd.JCmd
32311 MyAwesomeApplication
Notice how jcmd includes itself in the list? That's because it's also a Java application. Meta, isn't it?
Discovering Available Commands
Once you have your process ID, you can discover what diagnostic commands are available:
jcmd <PID> help
This returns a comprehensive list of available commands, which might include:
- JFR commands:
JFR.start,JFR.stop,JFR.dump,JFR.check - GC commands:
GC.heap_dump,GC.run,GC.class_histogram - Thread commands:
Thread.print - VM commands:
VM.flags,VM.system_properties,VM.uptime
The Heavy Hitters: Commands That Actually Save Your Day
Thread Dumps: When Your App Decides to Take a Nap
Thread dumps are your best friend when your application suddenly decides that responding to requests is overrated. The Thread.print command gives you a complete snapshot of all threads:
jcmd <PID> Thread.print
This command provides detailed information about each thread including its state, stack trace, and any locks it’s holding. It’s particularly useful for identifying deadlocks, performance bottlenecks, and threads that are stuck in infinite loops (we’ve all been there).
You can also save the output to a file for later analysis:
jcmd <PID> Thread.print > my_thread_dump.txt
Heap Dumps: Memory Detective Work Made Easy
When your application starts eating memory like it’s going out of style, heap dumps become invaluable. The GC.heap_dump command creates a snapshot of your heap:
jcmd <PID> GC.heap_dump /path/to/my_heap_dump.hprof
Pro tip: Always use absolute paths! Relative paths are interpreted from the JVM’s working directory, not your current directory. Trust me, you don’t want to spend 20 minutes hunting for a heap dump file.
For Java 11 and above, you can even compress the heap dump:
jcmd <PID> GC.heap_dump -gz /path/to/compressed_dump.hprof
The -gz option can save significant disk space and I/O time, especially with large heap dumps.
Flight Recorder: The Black Box for Your JVM
Java Flight Recorder (JFR) is like having a flight data recorder for your JVM. Starting a recording is straightforward:
jcmd <PID> JFR.start duration=60s filename=my_recording.jfr
You can also start continuous recordings with size and time limits:
jcmd <PID> JFR.start name=continuous_recording maxage=4h maxsize=400MB
To check the status of your recordings:
jcmd <PID> JFR.check
And to dump ongoing recordings without stopping them:
jcmd <PID> JFR.dump filename=snapshot.jfr
System Information: Know Your JVM
Sometimes you just need to know what flags your JVM is running with or what system properties are set:
# View VM flags
jcmd <PID> VM.flags
# View system properties
jcmd <PID> VM.system_properties
# View command line arguments
jcmd <PID> VM.command_line
# Check JVM uptime
jcmd <PID> VM.uptime
Garbage Collection Commands
Force garbage collection (though you probably shouldn’t in production):
jcmd <PID> GC.run
Get class histogram to see which objects are consuming memory:
jcmd <PID> GC.class_histogram
Advanced Use Cases: When Things Get Interesting
Performance Counter Analysis
jcmd can print performance counters that provide low-level JVM metrics:
jcmd <PID> PerfCounter.print
These counters give you access to internal JVM statistics that aren’t available through standard monitoring APIs. It’s like having x-ray vision into your JVM’s internal operations.
Batch Command Execution
You can execute multiple commands from a file using the -f option:
jcmd <PID> -f commands.txt
Where commands.txt contains one command per line:
Thread.print
GC.class_histogram
VM.flags
Working with Multiple JVMs
Send commands to all Java processes by using 0 as the process ID:
jcmd 0 VM.uptime
Or target processes by main class name instead of PID:
jcmd MyApplication GC.heap_dump /tmp/heap.hprof
Real-World Scenarios: When jcmd Saves the Day
Scenario 1: High CPU Usage Investigation
When your application is consuming excessive CPU:
- Take multiple thread dumps spaced apart:
jcmd <PID> Thread.print > thread_dump_1.txt
sleep 10
jcmd <PID> Thread.print > thread_dump_2.txt
-
Compare the dumps to identify hot threads
-
Use
GC.class_histogramto check for excessive object creation
Scenario 2: Memory Leak Detective Work
For suspected memory leaks:
- Start a continuous JFR recording:
jcmd <PID> JFR.start settings=profile duration=30m filename=memory_analysis.jfr
- Take heap dumps at intervals:
jcmd <PID> GC.heap_dump heap_before.hprof
# Run your application for a while
jcmd <PID> GC.heap_dump heap_after.hprof
Scenario 3: Production Troubleshooting
When you can’t restart the application:
- Check system properties and VM flags:
jcmd <PID> VM.system_properties | grep -i memory
jcmd <PID> VM.flags | grep -i heap
- Enable JMX without restart:
jcmd <PID> ManagementAgent.start_local
Why jcmd Should Be Your Go-To Tool
The real beauty of jcmd lies in its consolidation of functionality. Instead of remembering the syntax for jstack, jmap, jinfo, and other tools, you have one consistent interface. It's like having a universal remote for your JVM diagnostics.
Moreover, jcmd is actively maintained and receives new features with each JDK release, while some of the older individual tools are being deprecated or removed. Future-proofing your diagnostic scripts has never been easier.
Whether you’re debugging a production issue at 2 AM (we’ve all been there), optimizing memory usage, or just trying to understand what your application is actually doing, jcmd provides the insights you need without the complexity of external tools or additional setup.
So the next time your Java application starts acting like a moody teenager — consuming resources inexplicably, responding slowly, or just generally misbehaving — remember that jcmd is sitting right there in your JDK bin folder, ready to help you figure out what's going wrong. And unlike that moody teenager, it actually gives you useful, detailed answers.
메타데이터
- post_id
- 189d9cefa78e
- slug
- jcmd-the-swiss-army-knife-of-jvm-diagnostics-or-how-to-stop-wondering-what-your-java-app-is-189d9cefa78e
- url
- https://medium.com/@knpqvvzrb/jcmd-the-swiss-army-knife-of-jvm-diagnostics-or-how-to-stop-wondering-what-your-java-app-is-189d9cefa78e
- canonical_url
- https://medium.com/@knpqvvzrb/jcmd-the-swiss-army-knife-of-jvm-diagnostics-or-how-to-stop-wondering-what-your-java-app-is-189d9cefa78e
- author_url
- https://medium.com/@knpqvvzrb
- status
- ok
- fetched_at
- 2026-06-17 15:37:45