【问题标题】:Print full call stack on printStackTrace()?在 printStackTrace() 上打印完整的调用堆栈?
【发布时间】:2010-11-05 19:33:56
【问题描述】:

我需要编写一个小型日志分析器应用程序来处理由我的项目中使用的第 3 方封闭源代码库(内部具有自定义记录器)生成的一些日志文件。

如果日志中有异常条目,我需要收集有关沿堆栈跟踪从顶部到异常实际位置所涉及的方法的汇总信息。

不幸的是,默认情况下,Java printStackTrace() 不会打印调用堆栈中的每个方法,而是打印一定数量的方法,其余的只是引用为16 more...

如果我可以自己捕获异常,我会使用 getStackTrace() 并自己打印它,但根本原因永远不会包含在这个库抛出的异常中。

有没有办法让 Java 在堆栈跟踪中打印整个调用堆栈?

除了我的情况之外,常见的日志框架是否有这个选项?

编辑: 该程序在 Sun 的 JVM 上运行,JDK 1.5.0_09。没有办法改变它。

【问题讨论】:

标签: java logging stack-trace


【解决方案1】:

here is an explanation 的 'caused by' 和 '... n more' 行中的打印跟踪。另见JavaDoc for printStackTrace。你可能没有任何工作要做。

注意包含字符“...”的行的存在。这些行表明此异常的堆栈跟踪的其余部分与由此异常引起的异常(“封闭”异常)的堆栈跟踪底部的指定帧数相匹配。这种简写可以大大减少输出的长度,在这种情况下,包装的异常是从与捕获“原因异常”的相同方法中抛出的。

【讨论】:

  • 好点。当调用堆栈太大时,我可能将 ... 概念误解为简单的排序形式。我想当没有嵌套 100 帧深的根案例抛出异常时,我会在打印输出中得到那 100 行?
  • 我希望如此,但在 JavaDoc 中有一个关于 Throwable 的 getStackTrace() 的警告:“在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。”在 getOurStackTrace() 的核心,有两个本地方法可以控制这种行为:getStackTraceDepth() 和 getStackTraceElement(int index)
  • 谢谢。你能不能也反思一下第二个问题?有一天可能需要分析我自己的 log4j 输出。有一个完整的打印会简单得多,不用担心在原因和主要异常之间来回跳转。
  • 您正在寻找一种方法来打印堆栈而不考虑“原因”Throwable?
  • 在我上面的链接中,引用了 Appache 的 Commons Lang 库,它提供了一个 ExceptionsUtils 类。其中有一些助手可以打印“颠倒”的痕迹,这更容易理解。
【解决方案2】:

你不能用Thread.currentThread().getStackTrace()做点什么吗?

这是一个真正简单的例子,它递归调用一个方法 20 次,然后转储出当前线程的堆栈。

public class Test {
    public static void main(String[] args) {
        method();
    }

    static int x = 0;
    private static void method() {
        if(x>20) {
            StackTraceElement[] elements = Thread.currentThread().getStackTrace();

            for(int i=0; i<elements.length; i++) {
                System.out.println(elements[i]);
            }
        }
        else {
            x++;
            method();
        }
    }
}

【讨论】:

  • 引用:“如果我可以自己捕获异常,我会使用 getStackTrace() 并自己打印”
  • 所以你无论如何都无法控制代码?您只是在查看日志文件?再次阅读您的问题,我想不是。道歉!我会留下源代码,以防万一有人觉得它有用。
  • 它是用于一些遗留操作的第三方库。甚至不能在没有错误的情况下 JAD 它。根据 akf 的回答,我可能只是误解了堆栈跟踪打印输出格式。我很少有以编程方式分析堆栈跟踪的任务。
  • “如果我能自己捕捉到异常,我会使用 getStackTrace() 并自己打印” - 是的,但通常“Throwable”会传递给 Logger(Java Logging、SLF4J、Log4J ),并且您可以编写可插入的 Logger 实现以任何您想要的方式打印堆栈跟踪 :-)
【解决方案3】:

也许你可以尝试遍历返回的数组:

Thread.currentThread().getStackTrace();

【讨论】:

  • 引用:“如果我可以自己捕获异常,我会使用 getStackTrace() 并自己打印”
  • Thread 对象上的 getStackTrace() 方法应该返回当前线程的完整堆栈跟踪,不是吗?如果根异常是在同一个线程中引发的,它应该可以工作吗?可能我错过了什么..?
  • 库内部发生异常。它将这个异常堆栈跟踪记录到它的日志文件中,然后实例化它自己的异常(称为 LibException),其中包含根本原因的消息(LibException: FileNotFoundException ...),但不分配根本原因。该库很可能是为 Java 1.2 编写的,其中没有带有根本原因参数的构造函数,而 initCause() 方法是从 1.4 开始的。
猜你喜欢
  • 1970-01-01
  • 2015-07-01
  • 2010-11-28
  • 2011-05-15
  • 2010-11-23
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 2013-03-11
相关资源
最近更新 更多