和上篇内容并不重复
最近由于规则引擎有问题,导致产线上的一个 job 会抛 NullPointerException。本来这是个已知的问题,也没什么,已经联系对应的人去修复了。可由此发现了另外一个问题, fireman 的告警邮件只有异常的名称,而没有异常堆栈。
这就很令人懵圈了,因为不知道是已知的规则引擎的问题还是其他问题。
先看了下对应 job 的代码,确认打印异常的姿势是正确的, 本地也可以正常打印。然后去搜了下对应日期的 log 文件,确实有一堆 NPE 的报错,不过惊喜的发现在一开始的时候其实是有打出堆栈的,只是到后面就没有了。
最后终于在 stackoverflow 上找到了答案。
The compiler in the server VM now provides correct stack backtraces for all “cold” built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.
个人理解就是,JVM 为了性能会做优化,如果频繁的抛出某个异常,会重新编译,不再打印异常堆栈。
解决这个问题也比较简单,如果不想每次都去查前面的 log 去看堆栈,只要在启动参数加上 -XX:-OmitStackTraceInFastThrow
,就可以禁用该优化,强制打印异常堆栈。这样可能会导致,log 文件过大,不过产线上今天之前的 log 文件都会被压缩,所以感觉问题也不大。
Ps:用 iPic 上传图片真是好用到飞起,非常适合我这种喜欢插图星人,多谢洪菊的良心推荐。