NullPointerException丢失异常堆栈信息
源:http://blog.csdn.net/taotao4/article/details/43918131
评:
在生产环境上看到tomcat/log/catalina.out一直输出异常信息,但是不见异常堆栈信息。
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
在使用log4j中,调用异常方法exception.getStackTrace()获取到异常堆栈信息数组StackTraceElement[],然后使用方法log.error(Stringmsg)来循环打印StackTraceElement。(这种做法是不是很诡异-_-)。没发现任何与异常相关的信息打印出来。
java的标准输出在tomcat启动时,被管道重定向到了catalina.out,catalina.out信息来自所有标准输出。我们在catalina.out看到了信息,说明异常出现时,调用了标准输出,但是没有任何异常堆栈信息出来;我们在log4j配置的文件中没有找到任何异常信息说明StackTraceElement[]中没有任何信息。
最开始怀疑是log4j的使用方式有问题,导致打印不出来,但是当前的使用方式只会丢失rootCause,不会丢弃所有的异常堆栈。catalina.out中就以为是使用了标准输出打印异常类名...。事实当然不是这样,后来查看了异常处理点,基本上都会调用printStackTrace(),然后调用log4j来输出异常到其他文件。说明异常的堆栈信息确实丢失了。
异常堆栈丢失了,然后google之,stackoverflow答案。从别人的回答中,可以看到,这里可能是jvm优化时,产生的结果。具体参考文章
这里自己写的代码,在接近执行两万次时,确实看到异常堆栈信息就没有了:
[java]viewplaincopy
publicstaticvoidmain(String[]args){
inti=0;
Stringx=null;
while(i<100000000){
try{
System.out.println("当前执行次数为:"+i);
getNPE(x);
}catch(Exceptione){
intlth=e.getStackTrace().length;
System.out.println("length:"+lth);
e.printStackTrace();
if(lth==0){
return;
}
}
i++;
}
}
privatestaticvoidgetNPE(Stringx){
System.out.println("当前字母为:"+x.toString());
}
测试时java版本信息:
javaversion"1.7.0_71"
Java(TM)SERuntimeEnvironment(build1.7.0_71-b14)
JavaHotSpot(TM)64-BitServerVM(build24.71-b01,mixedmode)
当增加虚拟机参数-XX:-OmitStackTraceInFastThrow后,执行了100w次以上,也不见异常堆栈信息丢失。
看看oracle的官方解释:
ThecompilerintheserverVMnowprovidescorrectstackbacktracesforall"cold"built-inexceptions.Forperformancepurposes,whensuchanexceptionisthrownafewtimes,themethodmayberecompiled.Afterrecompilation,thecompilermaychooseafastertacticusingpreallocatedexceptionsthatdonotprovideastacktrace.Todisablecompletelytheuseofpreallocatedexceptions,usethisnewflag:-XX:-OmitStackTraceInFastThrow.
这里的"cold",个人以为是与hotspotVM中hot相对的意思,意思是非热点内置异常。如果异常被抛出数次,就变成”hot“了,这时就会丢失异常信息,因为这时的异常是预先分配的。
在查找资料的时候,发现淘宝定制的vm对这个功能有个开关,可以动态切换是否禁用此项优化。
参考链接:http://www.oracle.com/technetwork/java/javase/relnotes-139183.html