如何增加Java堆栈跟踪转储的显示行数?

时间:2009-07-22 20:03:50

标签: java exception

有没有办法让Throwable.printStackTrace(PrintStream s)打印完整的堆栈跟踪,这样我才能看到"... 40 more"的最后一行?

3 个答案:

答案 0 :(得分:112)

你不需要;该信息存在于堆栈跟踪的其他位置。来自printStackTrace()的文档:

  

请注意包含字符"..."的行的存在。这些行表示此异常的堆栈跟踪的剩余部分匹配由此异常(“封闭”异常)引起的异常的堆栈跟踪底部的指定帧数。

     

这种简写可以大大减少输出的长度,在这种情况下,从捕获“致使异常”的同一方法抛出包装异常。

换句话说,"... x more"仅出现在链式异常中,并且只有当堆栈跟踪的最后x行已作为另一个链式异常的堆栈跟踪的一部分出现时才会出现。

假设一个方法捕获异常Foo,将其包装在异常Bar中,并抛出Bar。然后Foo的堆栈跟踪将缩短。如果由于某种原因需要完整的跟踪,那么您需要做的就是在Foo的堆栈跟踪中的...之前的最后一行,并在Bar的堆栈跟踪中查找它;该行下方的所有内容都与Foo的堆栈跟踪中的内容完全相同。

答案 1 :(得分:5)

快速猜测一种方法。

static void printLongerTrace(Throwable t){
    for(StackTraceElement e: t.getStackTrace())
        System.out.println(e);
}

答案 2 :(得分:0)

让我们从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

原因从底部最嵌套的原因(“根本原因”)显示到打印堆栈跟踪所属的原因。

在这种情况下,根本原因是LowLevelException,这导致了MidLevelException,这又导致了HighLevelException

要获取完整的堆栈跟踪,必须查看封闭异常(及其封闭异常)的框架:

  1. 看看有多少帧被忽略:“ ... X more”
  2. 在封闭异常处查找省略的框架
    1. 看看省略了多少帧:“ ... Y 更多”
    2. 将前X-Y帧追加到堆栈跟踪中
  3. 如果Y> 0,请重复步骤2,将其作为省略帧的数量

因此,如果我们想获取LowLevelException的完整堆栈跟踪,我们将执行以下操作:

  1. 看看省略了多少帧:“ ... 3 更多”
  2. 在封闭异常(MidLevelException)处查找省略的帧
    1. 已省略1帧(“ ... 1 更多”)
    2. 将前2(3-1)帧追加到堆栈跟踪中
  3. 以第1步重复的步骤重复第2步
    1. 查看MidLevelExceptionHighLevelException)的封闭异常
    2. 将前一帧追加到堆栈跟踪中

您的完整堆栈跟踪如下:

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)

旁注:

  • 在某些情况下,可能不会列出任何框架,例如:

    HighLevelException: MidLevelException
        at Junk.main(Junk.java:4)
    Caused by: MidLevelException
        ... 1 more
    

    当原因在同一行new HighLevelException(new MidLevelException())中创建时,可能会发生这种情况。不要为此感到困惑,上面描述的方法仍然可以使用,除了异常,没有框架可以使用,继续将其封装起来。

  • 在某些情况下,您可以通过查看未被忽略的第一帧(... X more上方的行)来节省计数。如果您知道该行中的方法将调用该方法,则可以直接在封闭异常的框架中搜索调用者:

    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