How to Debug Java Errors
Debugging Java code for errors is a must-have skill for any developer. If an application crashes in a production environment, it can badly impact your business. You can prevent crashes and errors by spending time testing and debugging your code before deploying it.
There are several ways to debug Java code. When developing, you can use the tools available in your IDE or debugger. Once the application is deployed to production, you can capture the logs or use an error monitoring solution. Let’s explore each of these ways in more detail.
Debugging with Eclipse IDE
There are several ways to debug your code in Eclipse. Below are a few popular ways:
A conditional breakpoint: For debugging a Java code in Eclipse IDE, a breakpoint is a good approach. Applying breakpoints lets a debugger temporarily suspend the execution of your program at a certain point in the code. This allows you to examine the state of the application, the values of local variables, the call stack, and to step through the code line-by-line. This information gives you more clues to why the problem occurs. To set a breakpoint, just toggle it by clicking on the left-hand side of the screen.
Exception breakpoints: Runtime exceptions like NullPointerException and ArrayIndexOutofBoundException are the errors encountered most often. Figuring out the root cause of these errors can be difficult. Eclipse IDE offers exception breakpoints in which the execution of the program is stopped whenever the specified exception occurs.
Watch point: One of the best features of the Eclipse IDE, the watch point allows you to stop the execution of a program each time a targeted field or variable is accessed or changed. The watchpoint can be applied on a field or variable.
Step filtering: During debugging, you often jump from one class to another, or get into external libraries. If you don’t want these transitions, you can restrict them with the step filtering feature, which allows you to skip particular packages during the debugging process.
Evaluating (watch and inspect): This allows you to check the value of expressions while debugging Java programs. Right-click the statement and click on inspect. It will show you the value of the selected expression during the debugging process. The value will appear in front of you over the watch window.
Debugging Java errors in production
When running in production, you don’t have access to your debugger or IDE. Instead, you must rely on logs or air monitoring solutions to capture that data and store it for analysis. Here are tips for debugging in production.
Step 1: Increase the log level
Developers can often troubleshoot the cause if the logs contain a sufficiently detailed error message. However, the error message often doesn’t offer enough context. By increasing the log level to capture info or even debug logs, we get additional contextual information to help us determine the root cause.
Step 2: Retain logs
Centralizing logs to a server where they can be analyzed easily is equally important. Many companies offer log aggregation where you can create charts to keep an eye on trends in the logs. They also provide alerts so you can remain up to date on certain issues in the application.
Step 3: Examine the stack trace and other log information
Stack traces are very useful for debugging exceptions. A stack trace is a program’s attempt to tell you what functions have been called when the program crashed. Stack traces help in figuring out where something went wrong because they tell you where the problem occurred. You can see the order of calls made that resulted in the exception.
The example below shows how to print the stack of the exception using the printStack()
method of the exception class.
public class MainClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
String test = null;
try {
int length = test.length();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The code sample above will produce the following result.
java.lang.NullPointerException
at com.example.MainClass.main(MainClass.java:9)
Step 4: Attempt to replicate circumstances
Once the logs are retained, it is important to reproduce the situation at your end. To do this, you need to create the same environment so you can see the issue in the development environment. This helps in resolving the issue as you will be able to understand the environment and the code.
Step 5: Test assumptions
After you establish the scenarios that you think can throw the exception you are hunting down, it’s time to test them. It is not recommended to test exceptions in the production environment. For testing, it is good to use the development and staging environments since they don’t impact the end users.
Step 6: Adjust test parameters and try again
If you are not able to reproduce the issue in Step 4, adjust your test. Not every error is easy to reproduce. There are many reasons the issue may not be reproducible for you in the non-production environment. Go back to Step 3, adjust your test parameters, and try it again.
Debugging with Rollbar
The logs that the application generates often contain clues as to why a particular issue occurred. However, it is not easy to explore the log files and find the issue because errors may be duplicated thousands of times. Rollbar reduces the problem of information overload by grouping duplicate errors and providing developers summaries about how many errors happened and when. It also captures actual contextual information to help you debug the root cause of the problem, such as what browser they are using or what deployment may have introduced a bug. This helps you identify and fix errors faster.
As you can see the screenshot above, the traceback offers several details about the exception including title, filename, line number which helps you identify where the error came from in your code. It also provides additional contextual data like when it first started, number of occurrences, affected users with their browser/device OS and the IP address data. All this extra data will help you troubleshoot problems faster.
Troubleshooting errors with Rollbar
Let’s look at a Spring example which is generating an error. In the sections below, we will learn how to find the root cause of errors using Rollbar. We will also show you how to track who was affected so you can reach out and provide them support.
In the example below, the generateError()
method initializes Rollbar and then generates a test error. The ConfigBuilder
class configures Rollbar using the access token sets the environment name. Next, we have added a bug that is throwing a NullPointerException
. This is handled by try and catch, which reports error to the Rollbar.
@RestController
public class UserController {
Rollbar rollbar;
@RequestMapping("/rollbar/generateError")
public String generateError() {
// Rollbar setup
Config config = ConfigBuilder.withAccessToken("POST_SERVER_ACCESS_TOKEN")
.environment("Development").build();
rollbar = new Rollbar(config);
rollbar.init(config);
// Generate error
String test = null;
try {
test.toString();
} catch (Exception e) {
rollbar.error(e); //This is to send the errors to Rollbar Dashboard
return "Exception : " + e.getMessage();
}
return "SUCCESS";
}
}
Now we see an error sent to Rollbar, and looking at the stack trace we see the code file and line number where the error occurred.
at com.example.demo.UserController.testing(UserController.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Using source code integration
Rollbar can integrate with your source code repository in GitHub, Bitbucket, or GitLab. This allows Rollbar to link from your stack trace directly to the line in your source code, as shown below.
The above error is a NullPointerException. On line 69, you can see that the error has occurred due to calling the toString() method on the test variable, which was assigned a null value.
See the user impact of errors
Determining who was affected by a problem is often a key part of the puzzle, because there may be something about that user‘s profile data or permissions that caused the issue. Additionally, product managers often need to know who was affected in order to prioritize the highest impact problems. With the person tracking feature of Rollbar, you can find the users who are receiving the errors. This will help you reproduce the problem, and even reach out to those customers to provide extra support. You can track the people affected by adding a map of users when you report the error.
HashMap<String,Object> map=new HashMap<String, Object>();
map.put("Email","[email protected]");
rollbar.error(e,map);
Rollbar will now be able to show you the history of who was affected by each error, as well as a history of errors each user has experienced.
Resolving the problem
Once the error cause is identified, you can make fixes in the code. Rollbar is able to track the version history of your deployed code. It will tell you which errors were resolved, reactivated, and newly generated in each version. This is a great way to be confident that your fix resolves the error and that it didn’t cause any other issues.
An error monitoring solution like Rollbar gives you a lot more power to debug problems in production. It will help you fix problems faster, saving your development team time and helping you deliver a better user experience. Learn more about Rollbar’s features for Java and then sign up for a free trial.