SLF4j+Log4j2生产环境部分异常无法打印完整堆栈求助
异常日志仅输出一行,无法展示NullPointerException完整堆栈问题排查
环境信息
- SLF4j版本:1.7.22
- Log4j2版本:2.8.2
代码片段
异常捕获代码
try{ // Some code }catch (Throwable e){ logger.error("Occur exception -> ", e); }
同一类中不同方法对比代码
class A { private static Logger logger = LogManager.getLogger(A.class); void methodA(){ try{ // Some code }catch (Throwable e){ logger.error("Occur exception -> ", e); } } void methodB(){ try{ // Some code }catch (Throwable e){ logger.error("Occur exception -> ", e); } } }
日志输出
生产环境仅输出一行:
java.lang.NullPointerException: null
Log4j2配置文件(log4j2.xml)
<?xml version="1.0" encoding="UTF-8"?> <Configuration packages="com.changing" > <Appenders> <!-- DailyFile & Log file Name format by pattern --> <RollingFile name="DailyFile" fileName="C:/logs/log.log" filePattern="C:/logs/log-%d{yyyyMMdd}.log"> <PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%t] %c{2}:%L - %msg%n" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> </Policies> </RollingFile> </Appenders> <Loggers> <Logger name="com.contoso" level="debug"> <AppenderRef ref="DailyFile" /> </Logger> </Loggers> </Configuration>
异常现象细节
- 本地、测试环境可正常打印完整异常堆栈,生产环境仅输出一行异常信息
- 生产环境手动抛出异常时能打印完整堆栈,仅
NullPointerException出现时无法展示堆栈 - 同一类中,methodA捕获的异常仅输出一行,methodB捕获的异常可正常打印完整堆栈
排查方案
核心原因:JVM堆栈压缩优化
生产环境JVM大概率开启了-XX:+OmitStackTraceInFastThrow参数,该参数是JVM默认优化项:当同一位置频繁抛出特定类型异常(如NullPointerException、ArrayIndexOutOfBoundsException等)时,JVM会省略异常堆栈信息以提升性能。
如果methodA中的NullPointerException触发频率远高于methodB,就会出现前者无堆栈、后者有堆栈的差异;而手动抛出的异常触发频率低,JVM不会触发该优化,所以能打印完整堆栈。
解决步骤
- 检查生产环境JVM启动参数,确认是否包含
-XX:+OmitStackTraceInFastThrow - 修改JVM参数,添加
-XX:-OmitStackTraceInFastThrow(禁用该优化),或直接移除-XX:+OmitStackTraceInFastThrow参数 - 重启服务后,验证异常日志是否能正常打印完整堆栈
内容的提问来源于stack exchange,提问作者Ziv
相关产品推荐
相关产品推荐

