Java中没有StackTrace的NullPointerException

Edw*_*ern 308 java nullpointerexception

我有我们的Java代码的实例捕获NullPointerException,但当我尝试记录StackTrace(基本上最终调用Throwable.printStackTrace())时,我得到的是:

java.lang.NullPointerException
Run Code Online (Sandbox Code Playgroud)

还有其他人遇到过这个吗?我试过谷歌搜索"java空指针空堆栈跟踪",但没有遇到这样的事情.

Rol*_*lig 368

您可能正在使用HotSpot JVM(最初由Sun Microsystems,后来由Oracle收购,是OpenJDK的一部分),它执行了大量优化.要获取堆栈跟踪,您需要将选项传递-XX:-OmitStackTraceInFastThrow给JVM.

优化是当第一次发生异常(通常是NullPointerException)时,将打印完整的堆栈跟踪,并且JVM会记住堆栈跟踪(或者可能只是代码的位置).当该异常经常发生时,不再打印堆栈跟踪,以实现更好的性能,并且不会使用相同的堆栈跟踪泛洪日志.

要了解如何在HotSpot JVM中实现,请获取它的副本并搜索全局变量OmitStackTraceInFastThrow.上次我查看代码(在2019年),它位于文件graphKit.cpp中.

  • 以为我会添加额外的信息,当堆栈跟踪被优化掉时,这是因为它已经完全处理了至少一次:http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-以全输,他们-堆栈跟踪功能于生产和的修复/ (30认同)

Ste*_*ker 57

正如您在评论中提到的,您正在使用log4j.我(无意中)发现了我写过的地方

LOG.error(exc);
Run Code Online (Sandbox Code Playgroud)

而不是典型的

LOG.error("Some informative message", e);
Run Code Online (Sandbox Code Playgroud)

通过懒惰或者可能只是不考虑它.不幸的是,它不像你期望的那样表现.记录器API实际上将Object作为第一个参数,而不是字符串 - 然后它在参数上调用toString().因此,它不是获得漂亮的漂亮堆栈跟踪,而是打印出toString - 在NPE的情况下它是相当无用的.

也许这就是你所经历的?

  • 当然,但政策并不意味着它总能正确执行!想到它至少值得一提. (5认同)
  • 我们实际上有一个从不使用上面第一个表单的标准策略(LOG.error(exc);) - 我们总是使用2参数签名,以便我们在日志中添加一些描述性语句而不仅仅是原始堆栈跟踪. (3认同)

Mat*_*nit 27

我们过去曾见过同样的行为.事实证明,出于一些疯狂的原因,如果NullPointerException多次出现在代码中的相同位置,经过一段时间使用Log.error(String, Throwable)会停止包括完整的堆栈跟踪.

尝试进一步查看日志.你可能会找到罪魁祸首.

编辑: 这个错误听起来很相关,但它很久以前就被修复了,可能不是原因.

  • 帕维尔,你有没有试过约书亚建议的`-XX:-OmitStackTraceInFastThrow` JVM标志?另请参见http://stackoverflow.com/a/2070568/6198. (4认同)
  • 该错误已关闭,但仍需要 -XX:-OmitStackTraceInFastThrow 标志来解决性能优化问题。 (3认同)

Ben*_*out 19

以下是一个解释:Hotspot导致异常在生产中丢失堆栈跟踪 - 以及修复

我在Mac OS X上测试过它

  • java版"1.6.0_26"
  • Java(TM)SE运行时环境(版本1.6.0_26-b03-383-11A511)
  • Java HotSpot(TM)64位服务器VM(版本20.1-b02-383,混合模式)

    Object string = "abcd";
    int i = 0;
    while (i < 12289) {
        i++;
        try {
            Integer a = (Integer) string;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

对于这个特定的代码片段,12288次迭代(+频率?)似乎是JVM决定使用预分配异常的限制......

  • 回溯机链接:https://web.archive.org/web/20190911113910/http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-生产和修复/ (4认同)

Pet*_*ang 10

exception.toString 没有给你StackTrace,它只返回

这个throwable的简短描述.结果是连接:

* the name of the class of this object
* ": " (a colon and a space)
* the result of invoking this object's getLocalizedMessage() method
Run Code Online (Sandbox Code Playgroud)

exception.printStackTrace改用输出StackTrace.


Ste*_*ker 5

替代建议 - 如果您使用的是 Eclipse,则可以在 NullPointerException 本身上设置断点(在 Debug 透视图中,转到“Breakpoints”选项卡并单击其中带有 ! 的小图标)

检查“捕获”和“未捕获”选项 - 现在当您触发 NPE 时,您将立即断点,然后您可以逐步查看它是如何处理的以及为什么没有获得堆栈跟踪。