【问题标题】:Java Exception Stacktrace Not PrintingJava 异常堆栈跟踪未打印
【发布时间】:2012-09-04 12:37:41
【问题描述】:

我有以下代码:

import org.apache.commons.lang.exception.ExceptionUtils;
public void myMethod() {
    try {
        // do something
    } catch (Exception e) {
        System.out.println(ExceptionUtils.getStackTrace(e)); // prints "java.lang.NullPointerException"
        System.out.println(ExceptionUtils.getFullStackTrace(e)); // prints "java.lang.NullPointerException"
        e.printStackTrace(); // prints "java.lang.NullPointerException"
    }
}

我希望看到的输出是完整的堆栈跟踪,其中包含行号和失败的类的层次结构。例如,

Exception in thread "main" java.lang.NullPointerException
        at org.Test.myMethod(Test.java:674)
        at org.TestRunner.anotherMethod(TestRunner.java:505)
        at java.util.ArrayList(ArrayList.java:405)

这段代码正在一个更大的应用程序中运行,该应用程序也有 log4j,但我希望能够将异常转换为字符串,以便我可以将其作为电子邮件发送给 java 开发人员。

有人对如何将完整的堆栈跟踪捕获到字符串有任何想法吗?我不能使用 Thread.currentThread().getStackTrace(),因为这个应用程序在 Java 4 上运行。是什么阻止了上面的代码打印完整的堆栈跟踪?

【问题讨论】:

  • 看起来 NPE 中的 StackTraceElement 数组被重置为空。在 NPE 上有什么调用 setStackTrace 的吗?
  • @DanGravell - 不,不应该调用 setStackTrace。
  • 你能在 IDE 中调试它吗?可能值得在 catch 块中设置断点以查看异常是否“完美形成”。
  • 添加您的myMethod() 的记录输出或您的实际方法。 e.printStackTrace(); 通常应该打印填充轨迹。

标签: java exception logging exception-handling log4j


【解决方案1】:

什么可能会阻止上述代码打印完整的堆栈跟踪?

就我而言,我正在捕捉的Exception 的超类有以下代码:

/* avoid the expensive and useless stack trace for API exceptions */
@Override
public Throwable fillInStackTrace() {
    return this;
}

这意味着堆栈跟踪数组从未被填充,所以我得到的只是:

org.apache.kafka.AuthException: Auth failed: Invalid username or password

没有堆栈信息,所以不知道它发生在哪里。可爱。

我能够通过获取Exception 的源代码、将其复制到我的项目中并删除fillInStackTrace() 方法来覆盖此行为。这是一个 hack,但我需要来自 Exception 的信息。

【讨论】:

    【解决方案2】:

    确保您使用的是 e.printStackTrace(),而不是 e.getStackTrace();

    【讨论】:

      【解决方案3】:

      有人对如何将完整的堆栈跟踪捕获到字符串有任何想法吗?

      您可以使用以下方式(StringWriter.toString())将堆栈跟踪转换为字符串。

       StringWriter writer = new StringWriter();
       e.printStackTrace( new PrintWriter(writer,true ));
       System. out.println("exeption stack is :\n"+writer.toString());
      

      【讨论】:

        【解决方案4】:

        这是因为 java 在服务器模式下运行时会进行一些代码优化 (java -server) 跳过这个。在 java args 中使用 -XX:-OmitStackTraceInFastThrow 详情见以下链接:

        http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/

        【讨论】:

        • 我不会在生产服务器上关闭此优化,而是按照 Peter 的建议并查看日志中较早的错误。
        • 我同意当你拥有代码时可以做到这一点,如果你依赖别人,直到他们修复,这是你能做的最好的。
        • 这绝对是导致我在 Prod 上遇到类似问题的原因。谢谢你的回答!
        • 这在 OpenJDK7 上存在,但在 OpenJDK8 上不存在。
        【解决方案5】:

        我只能想到e.printStackTrace() 可能只输出字符串"java.lang.NullPointerException" 的两个原因。

        • 某些东西可能在异常上调用了setStackTrace(new StackTraceElement[0])
        • 异常对象可能是一个复杂类的实例,该类覆盖了printStackTrace() 或其他一些返回误导信息的方法。

        【讨论】:

          【解决方案6】:

          异常可能在你的 catch 块之前被捕获并抛出。也许在您调用的另一个类中执行逻辑。

          Exception 创建的类似于
          new Exception(new Throwable("java.lang.NullPointerException"));
          将打印您所看到的内容。

          【讨论】:

          • 事实证明,在 try 块内,它调用了另一个方法,该方法有一个 try 块,带有一个显式减少异常的 catch 语句(类似于你的示例,只是它们没有t 硬编码“NullPointerException”,而只是截断了堆栈跟踪的原因)。
          • @David - 我会认真考虑改用其他产品。故意压制这样的异常信息违背了客户/用户的最佳利益。寻找不做这种糟糕事情的替代供应商。
          【解决方案7】:

          如果您反复抛出异常,JVM 将停止填充堆栈跟踪。我不确定为什么,但可能是为了减少 JVM 的负载。您需要查看早期的堆栈跟踪才能查看详细信息。

          for (int n = 0; ; n++) {
              try {
                  Integer i = null;
                  i.hashCode();
              } catch (Exception e) {
                  if (e.getStackTrace().length == 0) {
                      System.out.println("No more stack trace after " + n + " thrown.");
                      break;
                  }
              }
          

          打印

          No more stack trace after 20707 thrown.
          

          【讨论】:

            【解决方案8】:

            可能是您没有控制台输出的附加程序。你考虑加一个。如果没有,将其记录为 LOGGER.error(ex);使用 log4j 或 SLF4J

            【讨论】:

            • 有一段时间,我认为这可能是由于控制台日志记录。所以我尝试将异常存储在一个字符串中并通过电子邮件发送给自己。该电子邮件仅包含“java.lang.NullPointerException”
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-01-18
            • 2010-09-18
            • 1970-01-01
            • 2012-03-03
            • 2014-08-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多