Exception
- 堆栈信息打印不完全
- 原因
JVM中有个参数:OmitStackTraceInFastThrow,字面意思是省略异常栈信息从而快速抛出,那么JVM是如何做到快速抛出的呢?
JVM对一些特定的异常类型做了Fast Throw优化,如果检测到在代码里某个位置连续多次抛出同一类型异常的话,
C2会决定用Fast Throw方式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,
因为不需要在堆里分配内存,也不需要构造完整的异常栈信息 - 效果
抛出了几千次带有详细异常栈信息的异常后,只会抛出java.lang.NullPointerException这种没有详细异常栈信息只有异常类型的异常信息。
这就是Fast Throw优化后抛出的异常。如果我们配置了-XX:-OmitStackTraceInFastThrow,再次运行,就不会看到Fast Throw优化后抛出的异常
,全是包含了详细异常栈的异常信息。 - 解决方案
OmitStackTraceInFastThrow和StackTraceInThrowable都默认为true,所以条件(!StackTraceInThrowable || OmitStackTraceInFastThrow)为true,
即JVM默认开启了Fast Throw优化。如果想关闭这个优化,很简单,配置-XX:-OmitStackTraceInFastThrow,
StackTraceInThrowable保持默认配置-XX:+OmitStackTraceInFastThrow即可。
- 堆栈信息封装为字符串(返回前端或者记录或者解决打印不完全)
public static String printStackTraceToString(Throwable t) {
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
} catch (Exception e) {
log.error("printStackTraceToString-异常",e);
} finally {
if(sw!=null){
try {
sw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(pw!=null){
pw.close();
}
}
return sw.getBuffer().toString();
}
- 异常覆盖
methodA抛出异常A methodB调用methodA try catch 后throw 异常B 就会把A覆盖掉(单个String参数构造方法) - 异常传递
两个String参数构造方法 - e.printStackTrace可能会发生异常需要try catch