Reading a Stack Trace in Java
A stack trace is the block of text Java prints when an exception isn't caught. Beginners often scroll past it, but it's the most useful debugging tool you have: it tells you what went wrong, where it happened, and how the program got there. Reading one takes about ten seconds once you know the three parts.
A Trace, Part by Part
public class Trace {
static int average(int[] marks) {
int sum = 0;
for (int m : marks) sum += m;
return sum / marks.length;
}
static void report(String name, int[] marks) {
System.out.println(name + ": " + average(marks));
}
public static void main(String[] args) {
report("Navika", new int[] {80, 90});
report("Srihitha", new int[] {});
}
}Navika: 85
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Trace.average(Trace.java:5)
at Trace.report(Trace.java:9)
at Trace.main(Trace.java:14)How to read it
- First line: what. The exception class and its message. "ArithmeticException: / by zero" already tells you an integer was divided by zero.
- Top
atline: where.Trace.average(Trace.java:5)means the methodaveragein classTrace, fileTrace.java, line 5. That's the exact line that threw. - Lines below: how you got there. Each
atline is a method call that was still in progress, newest first.averagewas called fromreportat line 9, which was called frommainat line 14 (Srihitha's report, with an empty array).
Your Code vs Library Code
When the exception starts inside the JDK or a library, the top lines belong to code you didn't write. Skip down to the first line from your own classes:
public class Marks {
static int total = 0;
static void read(String[] entries) {
for (String e : entries) {
String text = e.strip();
System.out.println("reading " + text);
total += Integer.parseInt(text);
}
}
public static void main(String[] args) {
String[] entries = {"80", "9O"};
System.out.println("start");
read(entries);
}
}Exception in thread "main" java.lang.NumberFormatException: For input string: "9O"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:565)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at Marks.read(Marks.java:8)
at Marks.main(Marks.java:15)The java.base/java.lang... lines are inside the JDK. The JDK isn't broken; it's reporting bad input. The first line from your code, Marks.read(Marks.java:8), is where you passed "9O" (with a letter O) to parseInt. Fix it there.
Caused by
When one exception is wrapped in another (see "Chained Exceptions in Java"), the trace shows both, with the original under Caused by::
Exception in thread "main" Chain$ReportException: Bad marks for Advitha: 9O
at Chain.parseMarks(Chain.java:10)
at Chain.main(Chain.java:15)
Caused by: java.lang.NumberFormatException: For input string: "9O"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:565)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at Chain.parseMarks(Chain.java:8)
... 1 moreThe top part describes the problem in your program's terms; the Caused by part shows the original, low-level failure. ... 1 more means the remaining frames are the same as in the trace above, so they aren't repeated. When a trace has several Caused by sections, the last one is usually the root cause.
Common Mistakes
Reading only the last line. The top lines usually matter most.
Blaming the JDK. Library frames at the top usually mean you passed it something invalid; find your first frame.
Printing only e.getMessage() in a catch. You lose the trace; log the exception itself or call e.printStackTrace() while debugging.
Interview Corner
How do you read a Java stack trace?
The first line gives the exception type and message, which describe what went wrong. The following "at" lines list the method calls active at that moment, from the most recent at the top to the oldest at the bottom, each with its class, method, file and line number. The topmost frame in your own code is usually where to start fixing. "Caused by" sections show wrapped original exceptions, and the last cause is typically the root cause.
Practice
- Easy: Run
Trace.java, then changemainso the empty array is passed first. How does the trace change? - Harder: Add a fourth method between
reportandmain, run it again, and match eachatline to a line of your code.
Key Takeaways
Was this tutorial helpful?