Java Debugging Best Practices

Debugging is a rather cumbersome process in the opinion of many developers. Though it’s aimed at detecting and fixing errors in the code, the process itself can be rather time-consuming and complex.

In order to facilitate the debugging process and make it more efficient, it is important to know about the best debugging methods available to the developers.

Java Debugging Best Practices

Debugging: special features and hidden rocks

When there is a bug that cannot be found and solved from the first look, the most obvious thing to do is to debug the executed part of the code. Most modern Java IDEs provide rich sets of tools for debugging an application. However, not every Java developer knows all the features provided by the debugger tool and all the debugging methods that make the developer’s life easier and the bugs’ life shorter.

Another thing to focus on – there are some pitfalls in debugging that developers need to know about. Due to its interactive nature, the code debugging process can be misleading. For example, multi-threaded applications do not behave in a way that a debugger shows us because the code is not really executed line by line. Instead, the execution flow is handled by many different threads and depends on their priority and different scenarios. This results in “underwater rocks” that can later transform into an issue.

Below I will talk about the most efficient debugging methods for Java applications. Please note that some of these methods can significantly slow down the execution. Thus, each method should be used wisely. 

Inside the debug mode

The most common instruments used for debugging a Java application are: step over, step into, and step out. 

Step over is used for debugging the code line by line. If it encounters a method call, it won’t go inside of this method but rather jump over it and continue the execution in the current context (the method is called, of course, but we won’t enter it in the debug mode). 

Step into is a way to accomplish this. When you stop on the line with the method call, click step into and the debugging will continue inside of this method. 

Step out is the way to exit the current method in order to get back to the parent context. During the debugging session, we can track the variables and objects’ values. This can help in resolving the bugs that are quite obvious. But for more complex issues, this method is not the most efficient one.  

Conditional breakpoint

During the code execution, we can set up a conditional breakpoint. This means that the application will stop its execution if a certain condition is satisfied. Thus, you won’t need to loop until the end to find the error condition.

Such breakpoints can help narrow down the investigation and check the current stack trace. Modern IDEs (such as Intellij IDEA and Eclipse) can provide a conditional breakpoint instrument for developers. All you need to do is to create a condition for a breakpoint. Multiple statements, including declarations, loops, and anonymous classes, can be used inside. 

Watch expression

Inside a debug window you can see a current context frame. Frames are added to a stack and contain watch expressions. When your application is stopped at some breakpoint, you can add a watch and see the current value of a specified variable. 

Watch is one of the most commonly used features provided by IDE’s debuggers. It indicates the value of the inserted statement represented by the current context. The values are updated every step through the application. When you exit the debug mode, frames are removed in the ‘last in – first out’ order. 

Exception breakpoint

When you see an exception that occurred during the program execution, the most common practice is to check a line where it occurred and to set up a breakpoint. But when this exception is thrown inside a loop that contains a thousand items, it’s better to use an exception breakpoint. 

An exception breakpoint is a breakpoint that stops an application on a specified line when an exception occurs. Thus, you need to specify the type of the exception inside your loop with a bug and set such a breakpoint. You will then be able to see the item that caused the issue. 

Field watch-point and Method breakpoint

The watch feature can also be used for class fields. All the field interactions will be “caught” by a debugger and the application will stop at a line where the usage of this field occurred. This option is especially helpful if you know or suppose what the issue might be. 

There is also a possibility to set a breakpoint on a method so that the debugger will track down and stop on each method call.

Debugging of long-running code

While being really helpful, features like field watchpoint or method breakpoint can also slow down the code execution. Even the conditional breakpoint can slow down the performance when processing the execution of the same code for a long time. 

Considering the fact that the code compiled by JVM is the fastest, we can introduce a condition to pause an application when a specific condition occurs. In order to do that we will use a simple endless loop. Here is an example: 

while (errorCondition(msg))
{
    System.out.println("condition met!");
    try
    {
        Thread.sleep(1000);
    }
    catch (InterruptedException e)
    {
        //ignore
    }

When an “errorCondition” returns true, the console will be bombarded with “condition met!” logs. Set a breakpoint inside to pause the application. This will allow you to see the stack trace and the current context. Then you can use watches to observe the values of the current execution frame.

There are multiple ways to exit a loop at the end:

  1. Use another feature of the debugger – Evaluate expression to modify the value returned by “errorCondition()” method.
  2. Another way is HotSwap presented by the Intellij IDEA debugger tool. This feature allows us to modify the running code during a debug session, compile it, and then the IDEA will swap the debugged classes with a new version.

Conclusion

In this article, we have observed the most efficient debugging methods for Java applications. I believe it should help you use the debugger tool more efficiently. And by doing so, you will be able to resolve the issues in a faster manner, better concentrate on building the architecture, and overall remain less stressed about the potential bugs.

Want to stay updated on the latest tech news?

Sign up for our monthly blog newsletter in the form below.

Softteco Logo Footer