| name | java-debugging |
| description | Debug Java applications including JVM flags, thread dumps, heap analysis, and common debugging patterns. Use when troubleshooting runtime issues, memory leaks, deadlocks, or performance problems in Java applications. |
Java Debugging Skill
Setup
Ensure you have a JDK installed with jcmd, jstack, and jmap available:
java -version
jcmd --help
Debugging Workflow
1. Check JVM Status
jcmd | grep -i java
jcmd <pid> VM.info
2. Thread Analysis
jcmd <pid> Thread.print > thread-dump.txt
jcmd <pid> Thread.print | grep -E "java.lang.Thread.State|\".*\""
Common thread states to look for:
BLOCKED — waiting for a monitor lock (potential deadlock)
WAITING — waiting indefinitely (LockSupport.park, Object.wait)
TIMED_WAITING — waiting with a timeout (Thread.sleep, wait(timeout))
RUNNABLE — actively executing or waiting for CPU
3. Deadlock Detection
jcmd <pid> Thread.print | grep -A 10 "Found deadlock"
jcmd <pid> Thread.print | grep -B 5 "BLOCKED"
4. Memory Analysis
jcmd <pid> GC.heap_dump /tmp/heap.hprof
jcmd <pid> GC.class_histogram | head -50
jcmd <pid> VM.native_memory summary 2>/dev/null || jcmd <pid> VM.flags | grep -i native
5. JVM Flags for Debugging
Common flags to add when starting the application:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/heapdump.hprof
-Xlog:gc*:file=gc.log:time,uptime
-XX:+PrintConcurrentLocks
-XX:+UnlockDiagnosticVMOptions -XX:+PrintDeadlockedThreads
-XX:StartFlightRecording=filename=/tmp/profile.jfr,duration=60s
Common Issues & Fixes
OutOfMemoryError
| Error | Cause | Fix |
|---|
java.lang.OutOfMemoryError: Java heap space | Heap too small or memory leak | Increase -Xmx, analyze heap dump with jcmd <pid> GC.class_histogram |
java.lang.OutOfMemoryError: Metaspace | Too many classes loaded (dynamic proxies, CGLIB) | Increase -XX:MaxMetaspaceSize, check for classloader leaks |
java.lang.OutOfMemoryError: Direct buffer memory | NIO direct buffers not GC'd | Reduce buffer size, ensure proper cleanup in finally blocks |
java.lang.OutOfMemoryError: GC overhead limit exceeded | GC spending >98% time recovering <2% heap | Increase heap, find memory leak, or disable with -XX:-UseGCOverheadLimit |
Slow Performance
- CPU-bound: Use
jcmd <pid> Thread.print to find hot threads, check for infinite loops or expensive operations
- GC pressure: Check GC logs with
jcmd <pid> VM.flags | grep -i gc
- Lock contention: Look for BLOCKED threads in thread dumps
Spring Boot Specific Debugging
logging:
level:
org.springframework.web: DEBUG
com.yourpackage: TRACE
curl http://localhost:8080/actuator/threaddump
curl http://localhost:8080/actuator/metrics/jvm.memory.used
curl http://localhost:8080/actuator/env
./mvnw spring-boot:run -Dspring-boot.run.arguments="--debug"
Debugging with the Toolkit
Using java_run for debugging sessions:
maven_run(projectDir=".", goals="spring-boot:run -Dspring-boot.run.jvmArguments=\"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\"")
Stopping a running app:
java_stop(projectDir=".")
Using java_dependency_tree for dependency conflicts:
When you see NoSuchMethodError or version conflicts, run:
java_dependency_tree(projectDir=".")
Note: java_run, maven_run, java_stop, and java_dependency_tree are provided by the Java Spring Tools extension (java-spring-tools.ts). This skill provides the debugging methodology and JVM diagnostics guidance; the tools above are used to execute those strategies.
Tips
- Always capture thread dumps with
jcmd rather than kill -3 for cleaner output
- Use
-XX:+HeapDumpOnOutOfMemoryError in production environments
- For long-running issues, enable GC logging:
-Xlog:gc*:file=gc.log:time,uptime
- Use
jstat -gc <pid> 1000 for real-time GC monitoring
- In Spring Boot, use
@ConditionalOnProperty to enable debug-only beans