JavaRush /Courses /Kotlin SELF /Debug in IntelliJ IDEA

Debug in IntelliJ IDEA

Kotlin SELF
Level 14, Lesson 6
Available

1. Bug

Programmers have their own slang. And the first word you’ll get closely familiar with will be the bug (from the English bug — an insect). This word means an error in a program that causes it to do something wrong, crash, or produce a weird result.

If a program behaves strangely but the programmer insists that’s exactly how it was intended, people usually say: “It’s not a bug, it’s a feature.” The internet is full of memes about this.

Meme about a bug and a feature

Historical note

Legend has it that in September 1947, Harvard scientists were testing the Mark II computer. It was malfunctioning. After checking all the contacts, they found a real moth stuck between relays. They taped the insect into the logbook with the caption “First actual case of bug being found” (the first real case of a bug being found).

Since then, the process of finding and fixing errors has been called debugging.

Photo of the first bug in the logbook


2. Debug Mode

To find an error, programmers use the Debugger. This is a special tool inside IntelliJ IDEA that lets you pause the program and “look under the hood.”

IntelliJ IDEA can run your program in two modes:

Mode Icon Keyboard shortcuts What it does
Run (Normal) Play icon Shift+F10 (Win/Lin)
Ctrl+R (Mac)
The program simply runs from start to finish.
Debug (Debugging) Bug icon Shift+F9 (Win/Lin)
Ctrl+D (Mac)
The program can stop at specified locations.

In debug mode, you can execute the program line by line (one line after another), watching how variable values change.

3. Breakpoints

For the Debugger to know where to stop, you need to set a Breakpoint. Without it, the program will just fly to the end as usual.

Let’s practice with a real example. Copy this code into IDEA:

fun main() {
    var sum = 0
    for (i in 1..5) {
        val result = i * 2  // <--- We want to stop here
        sum += result
        println("Step: $i, Result: $result, Sum: $sum")
    }
    println("Final Sum: $sum")
}

Task: We want to see how the sum variable changes inside the loop.

Action: Click with the mouse in the narrow gray gutter to the left of the line val result = i * 2. A red dot will appear.

Now run the program via Debug (the bug icon). The program will start and instantly “freeze” right before executing that line.

4. Controls: F8, F7, F9

When the program is paused, you have a control panel at the top of the Debugger tool window.

F8 — Step Over

Press F8. The program will execute the current line (the multiplication) and move to the next one (sum += result).

Press F8 again. The program will add the numbers. You’ll see how the variable values have changed.

Press F8 again. You’ll see output in the console.

This is the main way to move through code: line by line, without diving into details.

F9 — Resume Program

Our loop goes from 1 to 5. Pressing F8 five times to complete one loop iteration cycle is slow. And what if the loop has 1,000 iterations?

Press F9. The program will “unfreeze,” execute the rest of the code in the loop, go to the next iteration and... stop again at the breakpoint.

This way, with F9 you can quickly scroll through loops: one press — one iteration.

F7 — Step Into

Suppose we made our code a bit more complex and moved the multiplication logic into a separate function:

fun main() {
    var sum = 0
    for (i in 1..5) {
        val result = calculateMultiply(i) // <--- We want to stop here
        sum += result
        println("Step: $i, Result: $result, Sum: $sum")
    }
    println("Final Sum: $sum")
}

fun calculateMultiply(number: Int): Int {
    return number * 2
}

If on the line with the call val result = calculateMultiply(i) you press F8, the Debugger will simply execute it as a whole, instantly store the result in result, and move on. But if you want to see how the code works inside that function, press F7.

The Debugger will take you inside calculateMultiply, and you’ll see how the value of i is passed into the number parameter. This is indispensable when you’re looking for a bug inside a complex function.

Shift + F8 — Step Out

What if you accidentally pressed F7 on a line like println(...) and ended up deep inside Kotlin system code or Java sources? Reading thousands of lines of someone else’s code is boring and confusing.

Press Shift + F8. The program will quickly execute everything remaining in the current system function and take you back to where you came from (into your main function).

5. Where to view values?

Let’s return to our loop example.

Method 1: Inline Debugging

Look directly in the code editor. To the right of the lines, IDEA shows the current values in gray.

Method 2: Variables panel

At the bottom in the Debugger tool window, there is a Variables tab. It shows all variables. You can expand lists and objects to inspect their contents.

Method 3: Frames panel

To the left of the variables there is a list called Frames. It shows where the program is currently paused.

For example, the label main:4 (or main:4, MainKt) means:

  • You are in the main function.
  • You stopped at line 4.

This is your exact address in the code. If you step into another function (press F7), a new entry will appear at the top of this list.

6. Superpower: Evaluate Expression (Alt+F8)

Sometimes just looking at variables isn’t enough. You want to ask: “What happens if...”

Pause the program. Press Alt + F8 (Windows/Linux) or Option + F8 (macOS). The “Evaluate” window will open. You can also type expressions directly into the input line under the Variables panel.

Here you can write any code using the current variables. For example, in our loop type:

sum + 100

IDEA will calculate the result without changing the actual program. This is your scratchpad for experiments.

7. Conditional Breakpoints

Imagine you have a loop with 10,000 iterations, and the bug happens only on the 5,000th step. Pressing F9 five thousand times is a bad idea.

Right-click the red breakpoint dot. A pop-up window will appear. In the Condition field, enter a Java condition, for example: i == 4. Click Done.

Right-click on a Breakpoint showing the Condition field with i == 4 entered

Now, when you run the Debugger, the program will ignore the first 4,999 iterations and stop only when the condition becomes true. This can save you hours of work!

8. Managing all breakpoints

Sometimes beginners set so many breakpoints in different project files that the program keeps stopping in unexpected places. Searching for red dots across all files by hand takes a long time.

Press Ctrl + Shift + F8 (Windows/Linux) or Cmd + Shift + F8 (macOS). The Breakpoints window will open.

Breakpoints window (Ctrl+Shift+F8) showing a list of all active breakpoints with checkboxes

Here you’ll see a list of all breakpoints in your project. You can uncheck them (temporarily disable) or delete them using the Delete key.

9. Summary

We covered the core developer toolkit for finding errors. The Debugger is what turns writing code from “guessing by reading tea leaves” into precise engineering work.

The ability to quickly find the root cause of a bug is a skill that’s valued in development even more than the ability to write code fast. Practice—and no bug will get away from you.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION