Understanding Exception Stack Trace in Java with Code Examples
- Details
- Written by Nam Ha Minh
- Last Updated on 10 July 2019   |   Print Email
This Java exception tutorial helps you understand the concept of exception stack trace in Java and how to analyze an exception stack trace to detect bugs.
In this tutorial, we use the example in the article Understanding Java Exception Chaining with Code Examples. So kindly refer to that article while reading this one.
1. Analyzing an Exception Stack Trace
Look at the output of the StudentProgramexample:
StudentException: Error finding students at StudentManager.findStudents(StudentManager.java:13) at StudentProgram.main(StudentProgram.java:9) Caused by: DAOException: Error querying students from database at StudentDAO.list(StudentDAO.java:11) at StudentManager.findStudents(StudentManager.java:11) ... 1 more Caused by: java.sql.SQLException: Syntax Error at DatabaseUtils.executeQuery(DatabaseUtils.java:5) at StudentDAO.list(StudentDAO.java:8) ... 2 more
By examining this information we can find the root cause of the problem in order to fix bugs. In this exception stack trace, you see a list of chained exceptions which is sorted by the exception at the highest level to the one at the lowest level. This forms a stack like a stack of cards.
In each trace, we see the exception type (exception class name) along with the message:
StudentException: Error finding students
We also know the class, method and line number that raises the exception:
at StudentManager.findStudents(StudentManager.java:13)
This line tells us that the StudentException was thrown at line 13 in the method findStudents() of the class StudentManager.
And what causes the StudentException? Look at the next trace, we see:
Caused by: DAOException: Error querying students from database
That means the StudentException is caused by the DAOException which is thrown at line 11 in the method list() of the StudentDAO class.
Continue investigating further until the last exception in the trace, we see that the SQLException is actually the root cause and the actual place that sparks the exception is at line 5 in the method executeQuery() of the DatabaseUtils class:
Caused by: java.sql.SQLException: Syntax Error at DatabaseUtils.executeQuery(DatabaseUtils.java:5)
And here’s code of the DatabaseUtils class:
import java.sql.*; public class DatabaseUtils { public static void executeQuery(String sql) throws SQLException { throw new SQLException("Syntax Error"); } }
So basically that’s how we analyze the exception stack trace to find the root cause of the bug. The root cause is always at the bottom of the stack.
2. Preventing Exceptions Lost
Chaining exceptions together is a good practice, as it prevents exceptions from losing in the stack trace. Let’s modify the StudentDAO class like this:
import java.sql.*; public class StudentDAO { public void list() throws DAOException { try { DatabaseUtils.executeQuery("SELECT"); } catch (SQLException ex) { throw new DAOException("Error querying students from database"); } } }
Here we remove the SQLExceptioninstance (ex) from the DAOException’s constructor. Let’s compile and run the StudentProgram again, we would get the following output:
StudentException: Error finding students at StudentManager.findStudents(StudentManager.java:13) at StudentProgram.main(StudentProgram.java:11) Caused by: DAOException: Error querying students from database at StudentDAO.list(StudentDAO.java:11) at StudentManager.findStudents(StudentManager.java:11) ... 1 more
By comparing this exception stack trace with the previous one, we see that the SQLException disappears, right? That means the SQLException is lost in the stack trace though it is actually the root cause. When this happens, it’s hard to detect bugs exactly as the truth is hidden.
So you understand the importance of chaining exceptions together, don’t you?
3. Working with Exception Stack Trace
Besides the printStackTrace() method which prints out the detail exception stack trace, the Throwable class also provides several methods for working with the stack trace. Here I name a few.
- The printStackTrace(PrintStream) method writes the stack trace to a file stream. For example:
} catch (StudentException ex) { try { PrintStream stream = new PrintStream(new File("exceptions1.txt")); ex.printStackTrace(stream); stream.close(); } catch (FileNotFoundException fne) { fne.printStackTrace(); } }
- The printStackTrace(PrintWriter) method writes the stack trace to a file writer. For example:
} catch (StudentException ex) { // print stack trace to a PrintWriter try { PrintWriter writer = new PrintWriter(new File("exceptions2.txt")); ex.printStackTrace(writer); writer.close(); } catch (FileNotFoundException fne) { fne.printStackTrace(); } }
- The getStackTrace() method returns an array of StackTraceElement objects which allows us to access the stack trace programmatically. Here’s an example:
} catch (StudentException ex) { StackTraceElement[] stackTrace = ex.getStackTrace(); for (StackTraceElement trace : stackTrace) { String traceInfo = trace.getClassName() + "." + trace.getMethodName() + ":" + trace.getLineNumber() + "(" + trace.getFileName() + ")"; System.out.println(traceInfo); } }
Consult the Javadoc of the Throwable class to see more methods like fillInStackTrace(), setStackTrace(), etc.
4. A good practice about exception handling
Don’t handle exceptions in the intermediate layers, because code in the middle layers is often used by code in the higher layers. It’s responsibility of the code in the top-most layer to handle the exceptions. The top-most layer is typically the user interface such as command-line console, window or webpage. And typically we handle exceptions by showing a warning/error message to the user.
This good practice is illustrated by the following picture:
So remember this rule when designing and coding your program.
References:
Other Java Exception Handling Tutorials:
- 5 Rules about Catching Exceptions in Java
- Getting Started with Exception Handling in Java
- How to create custom exceptions in Java
- How to throw exceptions in Java - the differences between throw and throws
- Java Checked and Unchecked Exceptions
- Java exception API hierarchy - Error, Exception and RuntimeException
- Understanding Java Exception Chaining with Code Examples
- What you may not know about the try-catch-finally construct in Java
Comments
public static void main(String[] args) {
int t = 0;
for(int i = 1; i < 5; i++)
{
int d = 1;
for (int j = 1; j < i; j++)
d *= 10;
t += i * d;
System.out.println(t);
}
}
}