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)