Web Analytics

Debugging Techniques

Advanced ~15 min read

Effective debugging saves hours of development time. Master IDE debuggers, stack trace analysis, and remote debugging to quickly find and fix issues.

IDE Debugger Basics

IDEs like IntelliJ IDEA and Eclipse provide powerful debugging tools.

Debugger Controls

Action Shortcut (IntelliJ) Description
Toggle Breakpoint Ctrl+F8 Set/remove breakpoint on current line
Debug Shift+F9 Start debugging
Step Over F8 Execute line, don't enter methods
Step Into F7 Enter the method being called
Step Out Shift+F8 Exit current method
Resume F9 Continue until next breakpoint
Evaluate Expression Alt+F8 Run code in current context

Types of Breakpoints

  • Line Breakpoint: Pause at a specific line
  • Conditional Breakpoint: Pause only when condition is true
  • Exception Breakpoint: Pause when exception is thrown
  • Method Breakpoint: Pause when method is entered/exited
  • Field Watchpoint: Pause when field is accessed/modified
Pro Tip: Right-click a breakpoint to add conditions like userId == 42 or list.size() > 100. This avoids stopping on every iteration of a loop.

Reading Stack Traces

Stack traces show the sequence of method calls that led to an error.

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()"
    at com.example.UserService.validateEmail(UserService.java:45)
    at com.example.UserService.createUser(UserService.java:28)
    at com.example.UserController.register(UserController.java:15)
    at com.example.Main.main(Main.java:10)

How to Read It

  • Line 1: Exception type and message
  • Line 2: Where the exception occurred (start here!)
  • Lines 3+: Call chain that led to the exception
  • Read from top to bottom = most recent to oldest

Common Exceptions

Exception Likely Cause
NullPointerException Called method on null object
ArrayIndexOutOfBoundsException Invalid array index
ClassCastException Invalid type cast
NumberFormatException String can't be parsed as number
ConcurrentModificationException Modified collection while iterating
StackOverflowError Infinite recursion
OutOfMemoryError Memory leak or large data

Remote Debugging

Debug applications running on remote servers.

1. Start JVM with Debug Options

# Java 9+
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar app.jar

# Java 8
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar app.jar

2. Connect from IDE

In IntelliJ: Run → Edit Configurations → Add New → Remote JVM Debug

  • Host: localhost (or server IP)
  • Port: 5005
Security Warning: Never expose debug ports in production! Use address=127.0.0.1:5005 for localhost-only access, or use SSH tunneling for remote debugging.

Debugging Techniques

Binary Search Debugging

When you don't know where the bug is:

  1. Set breakpoint halfway through the code path
  2. Check if data is correct at that point
  3. If correct, bug is after; if wrong, bug is before
  4. Repeat until you find the exact location

Rubber Duck Debugging

Explain the code line by line (to a duck, colleague, or yourself). Often, you'll spot the bug while explaining.

Print Debugging (When All Else Fails)

public void processOrder(Order order) {
    System.out.println("DEBUG: order = " + order);
    System.out.println("DEBUG: order.items = " + order.getItems());
    System.out.println("DEBUG: order.items.size = " + order.getItems().size());

    // Better: Use logging with DEBUG level
    logger.debug("Processing order: {}", order);
}

JVM Debugging Tools

jps - List Java Processes

$ jps -l
12345 com.example.MyApp
67890 org.gradle.launcher.daemon.bootstrap.GradleDaemon

jstack - Thread Dump

# Get thread dump (find deadlocks, blocked threads)
$ jstack 12345 > thread-dump.txt

jmap - Memory Analysis

# Create heap dump for memory analysis
$ jmap -dump:format=b,file=heap.hprof 12345

# Analyze with tools like Eclipse MAT or VisualVM

VisualVM

GUI tool for monitoring and profiling Java applications:

  • Monitor CPU, memory, threads in real-time
  • Profile method execution times
  • Analyze heap dumps
  • Take thread dumps

Common Debugging Scenarios

NullPointerException

// Java 14+ shows helpful NPE messages:
// Cannot invoke "String.toLowerCase()" because "user.getName()" is null

// Debugging approach:
// 1. Look at the line number in stack trace
// 2. Identify which variable is null
// 3. Trace back where it should have been set
// 4. Add null checks or fix the source

// Prevention:
Optional.ofNullable(user)
    .map(User::getName)
    .ifPresent(name -> process(name));

Infinite Loop

// Symptoms: Application hangs, 100% CPU
// Debugging:
// 1. Take thread dump with jstack
// 2. Look for threads in RUNNABLE state
// 3. Check the stack trace for loop locations

// Common causes:
while (i < list.size()) {
    // Forgot to increment i!
    process(list.get(i));
    i++;  // Don't forget this!
}

Summary

  • Master IDE debugger shortcuts for efficiency
  • Use conditional breakpoints to stop only when needed
  • Read stack traces from top to bottom
  • Use remote debugging for server issues (securely!)
  • Use JVM tools (jstack, jmap) for production issues
  • Binary search to narrow down bug location