Working with Debugging
1. Using IDE Debugger
| Feature | Use |
|---|---|
| Breakpoints | Pause at line/method/exception |
| Step over/into/out | Navigate execution |
| Watch / evaluate | Inspect/compute expressions |
| Hot-swap | Reload changed methods (limited) |
2. Setting Breakpoints
| Type | Triggers |
|---|---|
| Line | Specific line |
| Conditional | When expression true |
| Exception | On throw of class |
| Field watchpoint | Read/write of field |
| Method | Entry/exit |
3. Using jdb Command Line Debugger
| Command | Use |
|---|---|
stop at Class:line | Set breakpoint |
run / cont | Start / continue |
step / next / step up | Navigate |
print expr | Evaluate |
where | Stack trace |
4. Remote Debugging
| Aspect | Detail |
|---|---|
| JVM flag | -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 |
| IDE | Attach to host:5005 |
| Production caution | Don't expose JDWP publicly — RCE risk |
5. Analyzing Thread Dumps
| Look For | Indicates |
|---|---|
| BLOCKED threads | Lock contention |
| WAITING on same monitor | Hot lock |
| Found Java-level deadlock | JVM detected deadlock |
| Many threads in same code | Bottleneck |
6. Analyzing Heap Dumps
| Tool | Use |
|---|---|
jcmd PID GC.heap_dump file.hprof | Capture |
-XX:+HeapDumpOnOutOfMemoryError | Auto on OOM |
| Eclipse MAT | Analyze (find leak suspects) |
| VisualVM | Lighter analysis |
7. Using Java Flight Recorder (JFR)
| Aspect | Detail |
|---|---|
| Overhead | < 1% with default settings |
| Records | Method profiling, GC, allocations, locks, I/O |
| Analyze | Java Mission Control (JMC) |
8. Using Java Mission Control (JMC)
| Tab | Shows |
|---|---|
| Method Profiling | Hot methods (flame graph) |
| Memory | Allocations by class/method |
| GC | Pause times, throughput |
| Lock instances | Contention |
9. Reading Stack Traces
| Element | Detail |
|---|---|
| Top frame | Where exception thrown |
| Caused by | Underlying root cause |
| Suppressed | From try-with-resources |
| Helpful NullPointerExceptions JAVA 14+ | Identifies which variable was null |
10. Logging Best Practices
| Practice | Detail |
|---|---|
| SLF4J facade | Decouple from implementation |
| Parameterized messages | log.info("User {} logged in", id) avoids string concat |
| Levels | ERROR / WARN / INFO / DEBUG / TRACE |
| Don't log secrets | Tokens, passwords, PII |
| Structured logging | JSON output for aggregation |
11. Using Assertions
| Aspect | Detail |
|---|---|
| Syntax | assert condition : "message"; |
| Enable | -ea JVM flag (off by default) |
| Use for | Internal invariants, not input validation |
12. Common Debugging Patterns
| Pattern | When to Use |
|---|---|
| Bisection | Narrow down failing change |
| Rubber duck | Explain code to find issue |
| Minimal reproduction | Strip to smallest failing case |
| Add logging strategically | Boundaries between components |
| Check assumptions | Print everything you "know" |
13. Troubleshooting Performance Issues
| Symptom | First Steps |
|---|---|
| High CPU | JFR profile + thread dump → identify hot methods |
| High memory | Heap dump + MAT → leak suspects |
| Long GC pauses | GC logs (-Xlog:gc*) + tune collector |
| Slow response | JFR latency events; check DB/network |
| Deadlock | Thread dump shows it explicitly |
14. Debugging Memory Issues
| Tool/Technique | Use |
|---|---|
-XX:+HeapDumpOnOutOfMemoryError | Capture at failure |
| Eclipse MAT "Leak Suspects" | Auto-identify hot paths |
| Dominator tree | Find what holds memory |
| Native Memory Tracking | -XX:NativeMemoryTracking=summary |
15. Debugging Concurrency Issues
| Issue | Approach |
|---|---|
| Deadlock | Thread dump → look for "Found one Java-level deadlock" |
| Race condition | JCStress for testing; logging with thread name |
| Livelock | Threads RUNNABLE but no progress |
| Starvation | JFR thread CPU time / lock contention events |
| Visibility bugs | Audit volatile/synchronized; consider VarHandle |