How do I increase the number of displayed lines of a Java stack trace dump?
Is there a way to 开发者_如何转开发make Throwable.printStackTrace(PrintStream s)
print the full stack trace, so that I can see beyond the final line of "... 40 more"
?
You don't need to; that information is present elsewhere in the stack trace. From the docs of printStackTrace()
:
Note the presence of lines containing the characters
"..."
. These lines indicate that the remainder of the stack trace for this exception matches the indicated number of frames from the bottom of the stack trace of the exception that was caused by this exception (the "enclosing" exception).This shorthand can greatly reduce the length of the output in the common case where a wrapped exception is thrown from same method as the "causative exception" is caught.
In other words, the "... x more"
only appears on a chained exception, and only when the last x
lines of the stack trace are already present as part of another chained exception's stack trace.
Suppose that a method catches exception Foo, wraps it in exception Bar, and throws Bar. Then Foo's stack trace will be shortened. If you for some reason want the full trace, all you need to do is take the last line before the ...
in Foo's stack trace and look for it in the Bar's stack trace; everything below that line is exactly what would have been printed in Foo's stack trace.
Let's take the stack trace from the documentation of Throwable.printStackTrace():
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
The causes are displayed from the most nested one at the bottom (the "root cause"), to the one which the printed stack trace belongs to.
In this case the root cause is LowLevelException
, which caused MidLevelException
, which caused HighLevelException
.
To get the complete stack trace you have to look at the frames of the enclosing exception (and its enclosing exceptions):
- Look at how many frames were omitted: "... X more"
- Look for the omitted frames at the enclosing exception
- Look at how many frames were omitted: "... Y more"
- Append the first X - Y frames to the stack trace
- If Y > 0, repeat step 2 with it as number of omitted frames
So if we wanted to get the complete stack trace of LowLevelException
we would do the following:
- Look at how many frames were omitted: "... 3 more"
- Look for the omitted frames at the enclosing exception (
MidLevelException
)- 1 frame has been omitted ("... 1 more")
- Append the first 2 (3 - 1) frames to the stack trace
- Repeat step 2 with 1 as number of omitted frames
- Look at the enclosing exception of
MidLevelException
(HighLevelException
) - Append the first 1 frame to the stack trace
- Look at the enclosing exception of
Your complete stack trace then looks like this:
LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
// From MidLevelException stack trace
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
// From HighLevelException stack trace
at Junk.main(Junk.java:4)
Side notes:
There might be cases where no frames are listed, e.g.:
HighLevelException: MidLevelException at Junk.main(Junk.java:4) Caused by: MidLevelException ... 1 more
This can happen when the cause it created in the same line:
new HighLevelException(new MidLevelException())
. Don't get confused by this, the approach described above still works, there are just no frames to use from the exception, continue with its enclosing one.In some cases you can save yourself the counting by looking at the first frame which was not omitted (the line above
... X more
). If you know which methods call the method in that line you can directly search for the callers in the frames of the enclosing exception:HighLevelException: MidLevelException: LowLevelException at Junk.c(Junk.java:29) at Junk.b(Junk.java:21) at Junk.a(Junk.java:13) at Junk.main(Junk.java:4) Caused by: MidLevelException // You know Junk.d is only called by Junk.b at Junk.d(Junk.java:35) ... 3 more
Quick guess at a method for you.
static void printLongerTrace(Throwable t){
for(StackTraceElement e: t.getStackTrace())
System.out.println(e);
}
精彩评论