Using the Debugger

Naveen AnamaneniUpdated · 6 min read

Your program compiles and runs, but the answer is wrong. You could sprinkle println lines everywhere and guess. Or you could pause the program at any line, look at every variable, and move forward one step at a time until you see exactly where it goes wrong. That's what a debugger does, and learning it early is one of the best habits you can build.

A Program with a Bug

This program should print the average of three test marks: 78, 92 and 86. They add up to 256, so the average should be about 85.33. Look at what it prints instead.

Average.java▶ Try it
public class Average {
    public static void main(String[] args) {
        int[] marks = {78, 92, 86};
        int total = 0;
        for (int mark : marks) {
            total = total + mark;
        }
        double average = total / marks.length;
        System.out.println("Total: " + total);
        System.out.println("Average: " + average);
    }
}
Output
Total: 256
Average: 85.0

The total is right, 256, but 256 / 3 should be 85.33, not 85.0. Where did the decimal part go? Let's find out with the debugger instead of guessing.

Set a Breakpoint and Start Debugging

A breakpoint is a marker on a line that says "pause here". The program runs normally until it reaches that line, then stops before running it.

  1. Open Average.java in your IDE.
  2. Click in the grey margin to the left of line 6. A red dot appears: that's your breakpoint.
  3. Start the program with Debug instead of Run (the bug icon, or Shift + F9 in IntelliJ IDEA on Windows and Linux).

The program pauses on line 6, and the Variables panel shows the current values: marks, total and mark.

Stepping through the loop and watching total change

Step Through the Code

These buttons control what happens next:

ButtonIntelliJ IDEA (Windows / Linux)What it does
Step OverF8Runs the current line and pauses on the next one
Step IntoF7If the line calls one of your methods, goes inside it
Step OutShift + F8Finishes the current method and pauses where it was called
ResumeF9Runs until the next breakpoint (or the end)
StopCtrl + F2Ends the program

Press Resume and the program runs round the loop once and pauses on line 6 again. Watch total in the Variables panel: 0, then 78, then 170. The loop is adding correctly. Now remove the breakpoint and Step Over until line 8 has run: total is 256, but average shows 85.0.

Use a Watch to Test an Idea

A watch is an expression the debugger works out for you at every pause. In the Variables panel, add these two watches:

  • total / marks.length shows 85
  • (double) total / marks.length shows 85.33333333333333

That's the bug. total and marks.length are both int, so Java does whole-number division first and gets 85. Only then is 85 stored in the double, as 85.0. The decimal part was already gone.

Here's the fixed line 8. Converting total to double first makes the division keep its decimal part:

AverageFixed.java▶ Try it
public class AverageFixed {
    public static void main(String[] args) {
        int[] marks = {78, 92, 86};
        int total = 0;
        for (int mark : marks) {
            total = total + mark;
        }
        double average = (double) total / marks.length;
        System.out.println("Total: " + total);
        System.out.println("Average: " + average);
    }
}
Output
Total: 256
Average: 85.33333333333333

Try it yourself: set a breakpoint on line 8 of AverageFixed and add a watch for average after stepping over it. Does it show the decimal part now?

Common Mistakes

Pressing Run instead of Debug. Breakpoints are ignored in a normal run. Use the Debug button.

Stepping into library code. Step Into on System.out.println can take you deep into Java's own classes. Use Step Out to come back, and Step Over for lines that only call library methods.

Changing code while paused and expecting it to apply. Most edits only take effect after you stop and debug again.

Leaving debugging println lines in the code. Once you've found the bug with the debugger, there's nothing to clean up. That's another reason to prefer it over println.

Practice

  1. Easy: Debug Average with a breakpoint on line 6 and write down the value of total at each pause.
  2. Harder: Change the marks to {90, 95, 100, 99} and use a conditional breakpoint so the debugger only pauses when mark == 100. What is total at that moment?

Quick check: Using the debugger

4 questions
1When does a breakpoint pause the program?
2You're paused on a line that calls your own method calculateFare(). Which button takes you inside that method?
3In the buggy Average, why was the average 85.0 instead of 85.33?
4What does a conditional breakpoint do?

Key Takeaways

Was this tutorial helpful?

Lesson 20 of 482