背景:
线上出现问题,去ELK 查看日志发现,没有栈堆信息,只有短短的
java.lang.ArrayIndexOutOfBoundsException: null
难道异常被吞掉了? 这... 咋排查问题😅😅😅
为什么会这样?
HotSpot VM 有个“吞Bug兽”,叫做Fast Throw:有些特定的隐式异常类型(NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、ArithmeticException( / 0)之类)如果在代码里某个特定位置被抛出过多次的话,HotSpot Server Compiler(C2)会默认的决定用fast throw来优化这个抛出异常的地方——直接抛出一个事先分配好的、类型匹配的异常对象。这个对象的message和stack trace都被清空。来提高性能,在高并发环境,性能差异是很大的;但缺点就是经过Fast Throw机制处理后我们看不到后续的 stack trace,就不好进行异常排查。从 JDK1.5 开始要避免C2做这个优化可以传个JVM参数:
-XX:-OmitStackTraceInFastThrow
模拟 Fast Throw
当报错的次数比较少的时候,异常的栈堆信息会正常打印出来
当报错的次数比较多的时候,异常的栈堆信息会被替换并置空
感兴趣的读者朋友可以看一下发布说明:https://sourl.cn/PMzVkC
结言
该特性默认是开启的,可以通过 -XX:-OmitStackTraceInFastThrow 关闭,关闭则会打印栈堆信息,但会提高性能消耗,在高并发的系统中关闭此项优化可能导致很严重的事故
评论区