生产环境抛异常,但却没有将堆栈信息输出到日志, logger.error(“exception“, e)

当Java生产环境中出现异常但日志堆栈信息缺失时,可能是因为JIT编译器的优化导致。JIT在某些异常频繁抛出时,会使用预分配的异常对象,这会导致堆栈跟踪信息丢失。为解决此问题,可以使用JVM参数-XX:-OmitStackTraceInFastThrow来禁止这种优化。此参数能确保在需要时获取完整异常堆栈,但可能影响性能。正常情况下,检查首次异常日志通常足以定位问题。

生产环境抛异常,但却没有将堆栈信息输出到日志,logger.error(“exception”, e),发现这个日志捕捉了NullPointerException,但是没有异常堆栈信息,只有java.lang.NullPointerException这一条信息,无法知道是从哪里抛出来的, 经过分析是JIT编译器对异常进行了优化,当代码中的某个位置抛出同一个异常很多次后,JIT服务端编译器(C2)会将其优化成抛出一个事先编译好的、类型匹配的异常,异常堆栈信息就看不到了。官方解释:
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.

引用R大的一段话:
HotSpot VM有个许多人觉得“匪夷所思”的优化,叫做fast throw:有些特定的隐式异常类型(NullPointerException、ArithmeticException( / 0)之类)如果在代码里某个特定位置被抛出过多次的话,HotSpot Server Compiler(C2)会透明的决定用fast throw来优化这个抛出异常的地方——直接抛出一个事先分配好的、类型匹配的异常对象。这个对象的message和stack trace都被清空。抛出这个异常的速度是非常快,不但不用额外分配内存,而且也不用爬栈;但反面就是可能正好是需要知道哪里出问题的时候看不到stack trace了。

从Sun JDK5开始要避免C2做这个优化还得额外传个VM参数:-XX:-OmitStackTraceInFastThrow。

解决方案:
JVM提供了-XX:-OmitStackTraceInFastThrow这个虚拟机参数来告诉JIT编译器禁用这种异常fastThrow的优化,当然如果你使用-Xint参数后虚拟机运行在解释器模式也不会出现这个问题,但是禁用JIT会对整体的性能有影响,因此不建议使用-Xint参数,如果想看到具体的异常堆栈,推荐使用-XX:-OmitStackTraceInFastThrow参数。

注意:
正常情况下如果日志有保留,则查询当次发布服务的第一条抛出的异常日志即可!后面的只作流水!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值