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

2022-08-31 10:29:52

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


答案 1

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

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

在捕获“致病异常”的相同方法引发包装异常的常见情况下,此速记可以大大减少输出的长度。

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

假设一个方法捕获异常 Foo,将其包装在异常 Bar 中,然后引发 Bar。然后Foo的堆栈跟踪将被缩短。如果您出于某种原因想要完整的跟踪,您需要做的就是在 Foo 的堆栈跟踪之前获取最后一行,然后在 Bar 的堆栈跟踪中查找它;那条线下面的一切都恰恰是Foo的堆栈跟踪中打印的内容。...


答案 2

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

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

在这种情况下,根本原因是,这导致了,这导致了。LowLevelExceptionMidLevelExceptionHighLevelException

要获得完整的堆栈跟踪,您必须查看封闭异常(及其封闭异常)的帧:

  1. 看看省略了多少帧:“...X更多”
  2. 在封闭异常处查找省略的帧
    1. 看看省略了多少帧:“...
    2. 将第一个 X - Y 帧追加到堆栈跟踪
  3. 如果 Y > 0,则以省略的帧数重复步骤 2

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

  1. 看看省略了多少帧:“...3更多”
  2. 在封闭异常处查找省略的帧 (MidLevelException)
    1. 省略了 1 个帧(“...1 更多“)
    2. 将前 2 (3 - 1) 帧追加到堆栈跟踪
  3. 重复步骤 2,将 1 作为省略帧数
    1. 查看封闭的例外MidLevelException (HighLevelException)
    2. 将前 1 帧追加到堆栈跟踪

然后,您的完整堆栈跟踪如下所示:

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