Java中没有StackTrace的NullPointerException

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

 java.lang.NullPointerException 

有没有人遇到过这个? 我试着用“java空指针空堆栈跟踪”的search结果,但没有遇到这样的事情。

您可能正在使用执行大量优化的Sun JVM。 要获取堆栈追踪,您需要将选项-XX:-OmitStackTraceInFastThrow传递给JVM。

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

 LOG.error(exc); 

而不是典型的

 LOG.error("Some informative message", e); 

通过懒惰,也许只是没有考虑到它。 这个不幸的部分是,它不符合你的期望。 logging器API实际上将Object作为第一个参数,而不是一个string – 然后它在参数上调用toString()。 所以,不是得到漂亮的堆栈跟踪,而是打印出toString – 这在NPE的情况下是相当无用的。

也许这是你正在经历的?

过去我们也见过这样的行为。 事实certificate,出于某种疯狂的原因,如果一个NullPointerException Log.error(String, Throwable)在代码中的相同位置出现,在使用Log.error(String, Throwable)一段时间后Log.error(String, Throwable)将停止包含完整的堆栈跟踪。

尝试在你的日志中回头看看。 你可能会find罪魁祸首。

编辑: 这个错误听起来有关,但它是很久以前修复它可能不是原因。

这里是一个解释: 热点造成exception在生产中丢失堆栈跟踪 – 以及修复

我已经在Mac OS X上testing过了

  • java版本“1.6.0_26”
  • Java(TM)SE运行时环境(build 1.6.0_26-b03-383-11A511)
  • Java HotSpot™64位服务器虚拟机(构build20.1-b02-383,混合模式)

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

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

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 

使用exception.printStackTrace来输出StackTrace。

备用的build议 – 如果你使用的是Eclipse,你可以在NullPointerException本身上设置一个断点(在Debug透视图中,进入“断点”标签并点击其中有一个!的小图标)

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

toString()只返回exception名称和可选消息。 我会build议打电话

 exception.printStackTrace() 

转储消息,或者如果您需要血淋淋的细节:

  StackTraceElement[] trace = exception.getStackTrace() 

这将输出exception,只用来debugging你应该更好地处理你的exception。

 import java.io.PrintWriter; import java.io.StringWriter; public static String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); t.printStackTrace(pw); pw.flush(); sw.flush(); return sw.toString(); } 

(您的问题仍然不清楚您的代码是否调用printStackTrace()或者这是由日志处理程序完成的。)

以下是关于可能发生什么的一些可能的解释:

  • 正在使用的logging器/处理程序已被configuration为仅输出exception的消息string,而不是完整的堆栈跟踪。

  • 您的应用程序(或某些第三方库)使用LOG.error(ex);loggingexceptionLOG.error(ex); 而不是(例如)log4j Logger方法的双参数forms。

  • 信息来自与你认为的不同的地方。 例如它实际上是来自一些第三方库的方法,或者是一些随机的东西,从早期的尝试来进行debugging。

  • 正在被logging的exception已经重载了一些方法来遮蔽栈跟踪。 如果是这样的话,这个exception将不是一个真正的NullPointerException,而是一些NPE的自定义子types,甚至是一些无连接的exception。

我认为最后一个可能的解释是不太可能的,但是人们至less会考虑做这种事情来“防止”逆向工程。 诚然,只有诚实的开发者才能真正成功。

在项目中使用AspectJ时,可能会发生某些方面隐藏了堆栈跟踪的部分。 比如今天我有:

 java.lang.NullPointerException: at com.company.product.MyTest.test(MyTest.java:37) 

这个堆栈跟踪是通过Maven的surefire运行testing时打印的。

另一方面,当在IntelliJ中运行testing时,会打印一个不同的堆栈跟踪:

 java.lang.NullPointerException at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67) at ... at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82) at ... at com.company.product.MyTest.test(MyTest.java:37)