【问题标题】:How to read the full stacktrace in Java where it says e.g. "... 23 more"如何阅读 Java 中的完整堆栈跟踪,例如“……还有 23 个”
【发布时间】:2010-06-03 22:53:16
【问题描述】:

我想读取我捕获的异常的完整堆栈跟踪。

例如:

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.ibm.db2.jcc.DB2Driver'
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1136)
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
 at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
 at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
 at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
 at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
 at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
 at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
 at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
 at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
 at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: COM.ibm.db2.jcc.DB2Driver
 at java.net.URLClassLoader$1.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClassInternal(Unknown Source)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Unknown Source)
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
 ... 23 more

我想阅读“... 23 more”以了解异常来自何处。

【问题讨论】:

标签: java stack-trace


【解决方案1】:

BalusC 是对的。见这里:http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html#printStackTrace()

特别是:

注意存在的行包含 那些角色 ”...”。这些行 表明剩余的 此异常的堆栈跟踪匹配 指定的帧数 堆栈跟踪的底部 由此引起的异常 异常(“封闭”异常)。 这个速记可以大大减少 公共输出的长度 包装异常的情况 从相同的方法抛出 捕获了“导致异常”。

这在你的例子中意味着:

BasicDataSource.java 第 1136 行捕获了第 1130 行抛出的 ClassNotFoundException 并将其重新提升为 SQLNestedException。因此,ClassNotFoundException 的堆栈跟踪的其余部分与上面的 SQLNestedException 匹配,并且堆栈跟踪以这种更简洁的格式打印。

【讨论】:

    【解决方案2】:

    答案很简单,这些行已经在堆栈跟踪中:)

     at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
     at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
     at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
     at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
     at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
     at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
     at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
     at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
     at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
     at java.lang.Thread.run(Unknown Source)
    

    基本上,BasicDataSource#createDataSource() 中发生了以下情况:

    try {
        Class.forName(driverClassName); // Line 1130
    } catch (ClassNotFoundException e) {
        throw new SQLNestedException(e, "Cannot load JDBC driver class '" + driverClassName + "'"); // Line 1136
    }
    

    【讨论】:

    • 好吧,现在过了很长时间,我读到答案很简单,这是一个 jar hell 问题(或者在这种情况下,缺少带有 DB2 驱动程序的 jar。它在:“引起:java.lang.ClassNotFoundException:COM.ibm.db2.jcc.DB2Driver”
    【解决方案3】:

    当外部异常 (SQLNestedException) 包装内部异常 (ClassNotFoundError) 时,它们位于同一个线程上,因此它们的堆栈跟踪共享一个共同的基础。

    (23 more...) 显示了内部异常的公共堆栈从哪里开始,这也是引发外部异常的地方。因此,每当您看到(XX 更多...)时,只需查看上面的异常即可查看堆栈跟踪的其余部分。

    如果您想以编程方式打印出没有省略号的堆栈跟踪,那么您可以使用Throwable.getStackTrace() 并自己打印出所有元素。

    【讨论】:

    • 感谢大家的回答 :) 这对我有很大帮助(了解我正在做的程序发生了什么)问候
    【解决方案4】:

    试试这个。此逻辑循环遍历主要异常及其所有原因,直到没有更多原因 (cause == null) 需要处理。这样您就可以避免 23 more... 消息。我尚未对此进行测试,但我相信这应该适合您。

    BTW - logWriter 是一个缓冲的写入器。您可能想要使用 System.out.print 或任何其他日志记录 API。

    public static void debugError(final String message, final Throwable th) {
        final String logMessage = "[ERROR] - " + message;
    
        try {
            logWriter.write(logMessage);
            logWriter.newLine();
    
            // dump exception stack if specified
            if (null != th) {
                final StackTraceElement[] traces = th.getStackTrace();
                if (null != traces && traces.length > 0) {
                    logWriter.write(th.getClass() + ": " + th.getMessage());
                    logWriter.newLine();
    
                    for (final StackTraceElement trace : traces) {
                        logWriter.write("    at " + trace.getClassName() + '.' + trace.getMethodName() + '(' + trace.getFileName() + ':' + trace.getLineNumber() + ')');
                        logWriter.newLine();
                    }
                }
    
                Throwable cause = th.getCause();
                while (null != cause) {
                    final StackTraceElement[] causeTraces = cause.getStackTrace();
                    if (null != causeTraces && causeTraces.length > 0) {
                        logWriter.write("Caused By:");
                        logWriter.newLine();
                        logWriter.write(cause.getClass() + ": " + cause.getMessage());
                        logWriter.newLine();
    
                        for (final StackTraceElement causeTrace : causeTraces) {
                            logWriter.write("    at " + causeTrace.getClassName() + '.' + causeTrace.getMethodName() + '(' + causeTrace.getFileName() + ':' + causeTrace.getLineNumber() + ')');
                            logWriter.newLine();
                        }
                    }
    
                    // fetch next cause
                    cause = cause.getCause();
                }
            }
        } catch (final IOException ex) {
            System.err.println(logMessage);
    
            if (null != th) {
                th.printStackTrace();
            }
        }
    }
    

    【讨论】:

    • 您可以使用Reader 读取printStackTrace 输出,直到它命中Caused by,然后获取原因并打印其堆栈跟踪(寻找下一个)...引起并递归地重复这个过程,直到没有更多的堆栈跟踪。这样您就不必构建自己的自定义堆栈跟踪格式化程序 - 您可以使用现有的 :)
    • 您的代码运行良好。要将跟踪发送到 system.out,我只需添加 BufferedWriter logWriter = new BufferedWriter(new OutputStreamWriter(System.out)); 并在末尾添加:logWriter.flush();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 2011-12-12
    • 1970-01-01
    • 2013-11-16
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多