NullPointerException丢失异常堆栈信息

狼烟烽火 2017-09-25

源: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

相关推荐

蜗牛慢爬的李成广 / 0评论 2019-10-19
CloudCraft / 0评论 2011-12-15