BLOG POSTS
    MangoHost Blog / Java Thread Dump: VisualVM, jstack, kill -3, jcmd Explained
Java Thread Dump: VisualVM, jstack, kill -3, jcmd Explained

Java Thread Dump: VisualVM, jstack, kill -3, jcmd Explained

When your Java application starts behaving unpredictably—threads hanging, CPU usage spiking, or the application becoming unresponsive—you need a thread dump to see what’s happening under the hood. A thread dump is essentially a snapshot of all threads running in a Java Virtual Machine at a specific moment, showing their state, stack traces, and what they’re doing. This post walks you through four essential methods for generating thread dumps: VisualVM’s GUI approach, the reliable jstack command, the old-school kill -3 signal, and the modern jcmd utility. You’ll learn when to use each tool, how to interpret the output, and common troubleshooting scenarios you’ll encounter in production environments.

What is a Java Thread Dump and Why You Need It

A thread dump captures the execution state of every thread in a JVM process at a specific point in time. Think of it as taking a photograph of your application’s internal activity—you can see which threads are running, waiting, blocked, or deadlocked.

Each thread dump entry contains:

  • Thread name and ID
  • Thread state (RUNNABLE, BLOCKED, WAITING, etc.)
  • Stack trace showing the current execution path
  • Monitor information for synchronization
  • Native thread ID for correlation with OS-level tools

Common scenarios where thread dumps become invaluable:

  • Diagnosing deadlocks between threads
  • Identifying performance bottlenecks and blocked threads
  • Analyzing thread pool utilization
  • Debugging infinite loops or hung processes
  • Understanding application behavior under load

Method 1: VisualVM – The Visual Approach

VisualVM provides the most user-friendly way to generate and analyze thread dumps through its graphical interface. It’s particularly useful when you need to correlate thread behavior with other metrics like memory usage or CPU consumption.

Setting Up VisualVM

VisualVM comes bundled with Oracle JDK distributions or can be downloaded separately. For JDK 9+, you’ll need to download it independently from the official VisualVM website.

# Launch VisualVM
$JAVA_HOME/bin/jvisualvm

# Or if installed separately
visualvm

Generating Thread Dumps with VisualVM

Once VisualVM is running:

  • Navigate to the “Applications” panel on the left
  • Locate your Java process (local or remote)
  • Right-click the process and select “Thread Dump”
  • The dump appears in a new tab with syntax highlighting

VisualVM’s thread dump viewer offers several advantages:

  • Color-coded thread states for quick visual scanning
  • Built-in deadlock detection with highlighted problem areas
  • Thread filtering and search capabilities
  • Integration with profiling data

Monitoring Threads in Real-Time

The “Threads” tab in VisualVM provides a timeline view showing thread activity over time. This helps identify patterns like:

  • Threads that frequently switch between states
  • Long-running operations
  • Thread pool starvation

Method 2: jstack – The Command Line Workhorse

jstack is the go-to command-line tool for generating thread dumps, especially in production environments where GUI tools aren’t available. It’s reliable, fast, and available in all standard JDK installations.

Basic jstack Usage

First, identify your Java process ID:

# List all Java processes
jps -v

# Or use ps with grep
ps aux | grep java

Generate a thread dump:

# Basic thread dump
jstack 

# Force thread dump (useful for hung processes)
jstack -F 

# Include additional information
jstack -l 

Practical jstack Examples

Save thread dump to file with timestamp:

# Single thread dump
jstack 12345 > threaddump_$(date +%Y%m%d_%H%M%S).txt

# Multiple dumps with interval (useful for trend analysis)
for i in {1..5}; do
  jstack 12345 > threaddump_${i}_$(date +%Y%m%d_%H%M%S).txt
  sleep 10
done

When jstack fails with “Unable to open socket file”, try:

# Run as the same user as the Java process
sudo -u  jstack 

# Or use force mode
jstack -F 

jstack Output Analysis

A typical jstack output looks like this:

2024-01-15 10:30:15
Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.0.1+12-LTS-39):

"http-nio-8080-exec-1" #25 daemon prio=5 os_prio=0 tid=0x00007f8b8c028000 nid=0x1a2b waiting on condition [0x00007f8b7c3fd000]
   java.lang.Thread.State: WAITING (parking)
   at sun.misc.Unsafe.park(Native Method)
   - parking to wait for  <0x000000076ab62208> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
   at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
   at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
   at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107)

Method 3: kill -3 – The Unix Signal Method

The kill -3 command sends a SIGQUIT signal to the Java process, instructing it to generate a thread dump. This method works reliably across Unix-like systems and doesn’t require additional JDK tools.

Using kill -3

# Send SIGQUIT signal
kill -3 

# Alternative syntax
kill -QUIT 

The thread dump output goes to wherever the JVM directs its standard error stream:

  • Application logs (if configured)
  • Console output (for interactive processes)
  • System logs like /var/log/messages

Locating kill -3 Output

Common locations to check:

# Check application logs
tail -f /path/to/application.log

# Check system logs
sudo journalctl -f -u your-java-service

# For Tomcat applications
tail -f $CATALINA_HOME/logs/catalina.out

# Check stderr redirection
ls -la /proc//fd/2

kill -3 Best Practices

  • Always verify the process ID before sending the signal
  • Monitor disk space—thread dumps can be large in applications with many threads
  • Use kill -3 when other tools fail or aren’t available
  • Combine with log rotation to prevent log file overflow

Configure log rotation for thread dumps:

# Example logrotate configuration
/var/log/myapp/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

Method 4: jcmd – The Modern Swiss Army Knife

jcmd is the most versatile and modern tool for JVM diagnostics, replacing several older utilities. It provides thread dumps plus additional diagnostic capabilities, making it the preferred choice for comprehensive troubleshooting.

Basic jcmd Operations

# List all Java processes
jcmd

# List available commands for a specific process
jcmd  help

# Generate thread dump
jcmd  Thread.print

# Thread dump with additional lock information
jcmd  Thread.print -l

Advanced jcmd Features

jcmd offers capabilities beyond simple thread dumps:

# VM classloader statistics
jcmd  VM.classloader_stats

# GC information
jcmd  GC.run
jcmd  GC.class_histogram

# System properties
jcmd  VM.system_properties

# JVM flags
jcmd  VM.flags

# Performance counters
jcmd  PerfCounter.print

jcmd Thread Dump Analysis

jcmd provides enhanced thread dump information:

# Comprehensive thread analysis
jcmd  Thread.print -l > comprehensive_dump.txt

# Example output includes:
# - Locked ownable synchronizers
# - Detailed lock information  
# - Thread CPU time
# - Allocated memory per thread

Tool Comparison and When to Use Each

Tool Best Use Case Pros Cons Availability
VisualVM Development, interactive analysis GUI interface, visual timeline, integrated profiling Requires X11 forwarding for remote use, resource intensive JDK 6-8 bundled, separate download for JDK 9+
jstack Production troubleshooting, scripting Lightweight, reliable, force mode available Limited output format, older tool All JDK versions
kill -3 Emergency situations, minimal toolset Always available on Unix, no JDK tools needed Output location varies, can’t control format Unix/Linux systems only
jcmd Comprehensive analysis, modern environments Multiple diagnostic features, detailed output Not available in older JDK versions JDK 7+

Real-World Troubleshooting Scenarios

Scenario 1: Deadlock Detection

When your application hangs completely, multiple thread dumps taken 10 seconds apart help identify deadlocks:

# Automated deadlock detection script
#!/bin/bash
PID=$1
for i in {1..3}; do
  echo "=== Thread dump $i at $(date) ===" >> deadlock_analysis.txt
  jcmd $PID Thread.print >> deadlock_analysis.txt
  sleep 10
done

# Analyze for deadlock patterns
grep -A 10 -B 5 "Found Java-level deadlock" deadlock_analysis.txt

Scenario 2: High CPU Usage Investigation

Correlate high CPU threads with Java threads:

# 1. Find high CPU threads
top -H -p 

# 2. Convert thread ID to hex
printf "%x\n" 

# 3. Generate thread dump
jstack  > cpu_investigation.txt

# 4. Search for the hex thread ID (nid) in dump
grep -A 20 "nid=0x" cpu_investigation.txt

Scenario 3: Memory Leak Through Thread Analysis

Combine thread dumps with heap analysis:

# Generate both thread and heap dump
jcmd  Thread.print > threads.txt
jcmd  GC.class_histogram > heap_classes.txt

# Look for accumulating thread patterns
grep -c "java.lang.Thread.State: WAITING" threads.txt

Best Practices and Common Pitfalls

Thread Dump Collection Best Practices

  • Take multiple dumps: Single dumps show a moment in time; series reveal patterns
  • Include timestamps: Always timestamp your dumps for correlation
  • Monitor disk space: Large applications can generate multi-megabyte dumps
  • Document context: Note what the application was doing when the dump was taken
  • Use consistent intervals: 10-30 second intervals work well for most scenarios

Common Pitfalls to Avoid

  • Wrong process ID: Always verify with jps before taking dumps
  • Insufficient permissions: Run as the same user as the Java process
  • Overloading the system: Don’t take dumps too frequently on production systems
  • Ignoring GC threads: JVM internal threads can provide important clues
  • Not checking for core dumps: Force dumps with -F can sometimes crash unhealthy processes

Thread Dump Analysis Tips

Focus on these key indicators:

# Thread states to investigate:
# BLOCKED - waiting for monitor lock
# WAITING - waiting for notification  
# TIMED_WAITING - waiting with timeout
# RUNNABLE - executing or ready to execute

# Common problematic patterns:
grep -c "java.lang.Thread.State: BLOCKED" threaddump.txt
grep -c "parking to wait for" threaddump.txt
grep -c "waiting for monitor entry" threaddump.txt

Integration with Monitoring and Automation

Automated Thread Dump Collection

Set up automated collection based on system metrics:

#!/bin/bash
# Auto-collect thread dumps when CPU exceeds threshold
JAVA_PID=$(pgrep -f "your-application")
CPU_USAGE=$(ps -p $JAVA_PID -o %cpu --no-headers)

if (( $(echo "$CPU_USAGE > 80" | bc -l) )); then
  DUMP_FILE="auto_threaddump_$(date +%Y%m%d_%H%M%S).txt"
  jcmd $JAVA_PID Thread.print > $DUMP_FILE
  echo "High CPU detected: $CPU_USAGE%. Thread dump saved to $DUMP_FILE"
fi

Integration with APM Tools

Many Application Performance Monitoring tools can trigger thread dump collection:

  • New Relic’s thread profiler integration
  • AppDynamics thread dump automation
  • Custom Prometheus/Grafana alerting with script execution
  • ELK stack integration for thread dump log analysis

Thread dumps are essential tools for Java application troubleshooting, and each method—VisualVM, jstack, kill -3, and jcmd—has its place in your diagnostic toolkit. Start with jcmd for modern JVMs when you need comprehensive information, fall back to jstack for reliable command-line access, use kill -3 in emergencies, and leverage VisualVM when you need visual analysis during development. Remember that effective thread dump analysis often requires multiple samples and correlation with other system metrics to identify the root cause of performance issues.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked