Raising insights from dead threads.
JVM Thread Dump Analysis for Claude Code.
Part of the SegfaultSorcerer Java Tooling Ecosystem.
4 slash commands. 2 automation hooks. Zero config to get started.
Why? • Skills • Hooks • Installation • How It Works • What It Detects • Synergies • Contributing
Thread dumps are one of the most powerful JVM diagnostic tools — and one of the most underused.
A production JVM app easily has 200+ threads. A raw thread dump is a wall of text: thousands of lines of stack traces, lock addresses, and JDK internals. Most developers can spot an obvious deadlock but miss the subtle patterns — connection pool exhaustion creeping in, a synchronized bottleneck serializing requests, a transaction holding a database connection hostage during an HTTP call to a slow external service.
thread-necromancer turns that wall of text into structured, actionable analysis. It captures thread dumps, parses them into meaningful sections, identifies known anti-patterns, and produces a prioritized report with concrete fix suggestions — complete with config properties and code examples.
Works with any JVM application — Spring Boot, Quarkus, Micronaut, Vert.x, Dropwizard, or plain Java. Framework-specific patterns (thread naming, proxy detection, scheduler defaults) are detected automatically.
No SaaS. No GUI. Just your terminal and Claude.
| Command | Description |
|---|---|
/thread-dump [PID] |
Capture a live thread dump and analyze it |
/thread-analyze <file> |
Analyze an existing thread dump file |
/thread-watch [PID] |
Capture multiple dumps over time, analyze progression |
/thread-compare <f1> <f2> |
Diff two thread dumps, identify changes |
Discovers running JVM processes, captures a thread dump via jcmd (or jstack as fallback), and produces a structured analysis report covering:
- Thread state distribution with health assessment
- Deadlock detection (JVM-reported + implicit lock chain analysis)
- Blocked thread clusters — groups of threads waiting at the same point
- Thread pool health — sizing, utilization, exhaustion
- Lock contention hotspots — which locks have the most waiters
- Framework-specific findings — Spring, Quarkus, Micronaut, Vert.x patterns detected automatically
- Top 3 prioritized actions with concrete config/code fixes
Example output
## Thread Dump Analysis Report
### Thread State Distribution
| State | Count | Percentage | Assessment |
|---------------|-------|------------|----------------------|
| RUNNABLE | 23 | 9.3% | Healthy |
| WAITING | 147 | 59.5% | High — check below |
| TIMED_WAITING | 45 | 18.2% | Normal |
| BLOCKED | 32 | 13.0% | Contention! |
### Contention Hotspots
| Severity | Lock / Monitor | Waiting | Holder |
|----------|----------------------------|---------|---------|
| CRITICAL | HikariPool.getConnection | 147 | exec-42 |
| CRITICAL | LegacyService.synchronized | 23 | exec-17 |
### Top 3 Actions
1. [CRITICAL] Increase HikariCP pool size — 147 threads blocked
spring.datasource.hikari.maximum-pool-size: 20
2. [CRITICAL] Replace synchronized with ReentrantLock in LegacyService
3. [WARNING] Increase @Scheduled pool size from default 1
spring.task.scheduling.pool.size: 5
Captures multiple dumps at configurable intervals and compares them to distinguish truly stuck threads from momentary contention:
- Stuck threads — same state + same stack across all dumps
- Progressing threads — changed state or moved in call stack
- Thread count drift — detecting thread leaks
- Contention trends — getting worse, resolving, or stable
- Lock holder duration — how long a thread has been holding a lock
Compares two thread dumps to show what changed:
- State transitions per thread (RUNNABLE → BLOCKED)
- New/disappeared threads (pool scaling, thread creation/death)
- Cluster size changes (contention improving or worsening)
- Lock holder changes
Both hooks are opt-in via flag files:
| Hook | Trigger | Flag File |
|---|---|---|
| Thread dump on test hang | Test command times out | .thread-necromancer/dump-on-test-hang.enabled |
| Startup thread baseline | Spring Boot app starts | .thread-necromancer/startup-baseline.enabled |
Enable a hook:
mkdir -p .thread-necromancer
touch .thread-necromancer/dump-on-test-hang.enabled
touch .thread-necromancer/startup-baseline.enabledFrom within Claude Code:
/plugin marketplace add SegfaultSorcerer/thread-necromancer
/plugin install thread-necromancer@thread-necromancer
git clone https://github.com/SegfaultSorcerer/thread-necromancer.git
cp -r thread-necromancer/skills/ your-project/.claude/skills/
cp -r thread-necromancer/hooks/ your-project/.claude/
cp thread-necromancer/scripts/* your-project/.claude/scripts/Requires a JDK (not just JRE) for thread dump capture tools.
| Requirement | Minimum | Recommended |
|---|---|---|
| JDK | 11+ | 17+ |
| Claude Code | latest | latest |
| OS | any | any |
Check your setup:
# macOS/Linux
./scripts/check-prerequisites.sh
# Windows (PowerShell)
powershell -File scripts/check-prerequisites.ps1Platform support:
- Thread dump parser (
run-parser.sh/run-parser.ps1): auto-discovers JDK 11+ from PATH, JAVA_HOME,~/.jdks, SDKMAN, Homebrew, and common install locations - Dump collector: Bash (
dump-collector.sh) on macOS/Linux, PowerShell (dump-collector.ps1) on Windows - Docker: Works if the JDK is in the container. For JRE-only containers, use
jstackfrom the host.
You Claude Code JVM
| | |
| /thread-dump | |
|------------------------>| |
| | dump-collector.sh list |
| |------------------------->|
| | <PID list> |
| |<-------------------------|
| "Analyze PID 12345" | |
|------------------------>| |
| | dump-collector.sh |
| | capture 12345 |
| |------------------------->|
| | <raw thread dump> |
| |<-------------------------|
| | |
| | DumpParser.java |
| | 6000 lines → 250 lines |
| | |
| | Claude analyzes with |
| | reference material: |
| | - thread-states.md |
| | - common-patterns.md |
| | - spring-patterns.md |
| | |
| Structured report | |
| with Top 3 Actions | |
|<------------------------| |
thread-necromancer works with zero configuration. All output goes to .thread-necromancer/dumps/ in your project root (auto-created, gitignored).
Optional settings via flag files in .thread-necromancer/:
| File | Effect |
|---|---|
dump-on-test-hang.enabled |
Auto-capture dump when tests hang |
startup-baseline.enabled |
Capture baseline dump after Spring Boot starts |
| Pattern | Severity | What You'll See |
|---|---|---|
| Connection pool exhaustion | CRITICAL | Threads WAITING at HikariPool.getConnection() |
| Synchronized bottleneck | CRITICAL | Threads BLOCKED at synchronized method |
| Deadlock | CRITICAL | JVM-reported circular lock dependency |
| Thread pool exhaustion | CRITICAL | All pool threads busy, no idle capacity |
| External service timeout | WARNING | Threads RUNNABLE at SocketInputStream.read() |
| Scheduler pool = 1 | WARNING | Single scheduling thread, tasks queuing |
| Transaction + HTTP call | WARNING | DB connection held during external call |
| Event loop blocking | WARNING | Blocking I/O on Netty/Vert.x event loop |
| Thread leak | WARNING | Growing thread count across dumps |
| @Async pool exhaustion | WARNING | Tiny async pool, tasks rejected |
| Open-in-view lazy loading | INFO | Hibernate proxies in controller layer |
thread-necromancer works alongside other SegfaultSorcerer tools:
| Tool | Synergy |
|---|---|
| spring-grimoire | /spring-jpa-audit finds N+1 queries → /thread-dump shows the connection pool impact |
| heap-seance | Memory analysis shows what's allocated → thread analysis shows who's allocating |
| gc-exorcist (planned) | GC pauses cause thread freezes → temporal analysis detects "all threads paused" |
See CONTRIBUTING.md.
Dual-licensed under MIT and Apache 2.0, at your option.
