log 不打印异常堆栈

和上篇内容并不重复 🙃

最近由于规则引擎有问题,导致产线上的一个 job 会抛 NullPointerException。本来这是个已知的问题,也没什么,已经联系对应的人去修复了。可由此发现了另外一个问题, fireman 的告警邮件只有异常的名称,而没有异常堆栈。
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 上传图片真是好用到飞起,非常适合我这种喜欢插图星人,多谢洪菊的良心推荐。
敲好用

分享到 评论