Line breakpoints are useful, but there are several other places where it can be helpful to stop execution:
When the primary constructor is invoked.
When a particular method is invoked. Including one that's been overridden or one with incorrect or missing source code.
When an exception of a specific type is thrown.
The next line of the current method, when program execution has already been stopped.
The first line of the method that's going to be invoked and added to the call stack next.
The next line of the caller method after the currently executing method is popped from the call stack.
The next line of the current method could be reached with another breakpoint, although there's a simpler way to do this. But the other places listed above cannot easily be reached with a line breakpoint. So, in this topic, you will learn about some additional tools that make this advanced kind of debugging possible.
Constructor and method breakpoints
To set a method breakpoint, click in the gutter against the method declaration and you will see a diamond breakpoint indicator:
The execution will stop at the first line of the method:
A primary constructor might not contain any statements and may not even have any property declarations or parentheses.
To set a constructor breakpoint, click in the gutter against the class declaration. You will see a diamond instead of a circle, and the execution will stop right inside the constructor, which is called <init> in the bytecode:
Using this tool, you can trace constructor invocations, even when dealing with classes that have implicit constructor declarations.
You can set a breakpoint on a method in a similar way. When debugging compiled code, you can see decompiled classes, but there can be mismatch between line number information and the sources. Also, when debugging Android framework, the source code in the IDE might be a different version from the Android version running on the device. So, line breakpoints would refer to the wrong lines, but method breakpoints will still work.
In the below example, a breakpoint has been set on the View.isEnabled() method, which comes from Android framework. The "current" line is highlighted incorrectly, but stack and this are still available and correct:
Exception breakpoints
When an application crash occurs, you can see its stack trace, but that's not always enough. Walking through stack frames and observing application state just before the crash could be very helpful.
Pressing Run → View Breakpoints... enables you to see all the current breakpoints and to set exception breakpoints:
Kotlin uses the same exception machinery as Java, so click the Java Exception Breakpoints option. Having done this, you can choose any of the exception types available in the current project and configure whichever details you want. For example, you can opt to stop on caught exceptions, uncaught exceptions, or both.
Done! Now, execution will stop when an exception that meets the specified conditions is thrown.
Stepping
So, you have a program stopped at a breakpoint. But what happens when the next line is executed? Or several lines later? Which method override will be invoked? What will happen after the current method returns?
There are also four items highlighted in the above screenshot:
Step Over
Step Into
Step Out
Run to Cursor
Step Over will resume execution to the next line, without traveling into any of methods called from the current one. This can be useful if you want to examine the execution of your code line by line.
Step Into will step into the next method called by the current line, or just step over if there's none. There's also Force Step Into (which has the same icon as Step Into but with a red arrow instead of a blue one). This tool makes it easy to step into library code instead of staying at the level of your own code. Force Step Into will work even without source code, and for runtime-generated classes without bytecode available. In this case, you won't see the code being executed, but stack frames will still be visible, giving you an idea about what that method does.
Step Out will suspend execution after the current method ends and return you to the context of the caller method.
In addition, you can use Run to Cursor. If you hover over a line number, the line will be highlighted. And if you click it, the program will resume until it reaches the clicked line and then be suspended again. This means that instead of adding a breakpoint and resuming, you can simply click the desired line.
Conclusion
You already knew about line breakpoints, and now you're familiar with constructor, method, and exception breakpoints as well. You've also learned how to continue execution until a particular line is reached, and determine which line will be executed next. In addition, you've seen how to peek into the depths of a method invocation chain and quickly return from it.