应传递异常对象而非仅 message,主流日志框架支持 Throwable 参数自动输出堆栈;需配置日志 pattern 含 %ex;JVM 快速抛出优化时加 -XX:-OmitStackTraceInFastThrow;脱敏等定制需求可用 getStackTrace() 手动构造。

只打印 e.getMessage() 会完全丢失堆栈信息,根本看不出异常在哪一行、经过哪些方法调用——这等于把诊断线索全删了。
别只传 message,要把整个异常对象传给日志方法
Log4j、SLF4J 等主流日志框架都支持 Throwable 参数重载。只要把异常对象作为最后一个参数传进去,堆栈就会自动附加:
-
✅ 正确写法:
logger.error("文件读取失败", e); -
❌ 错误写法:
logger.error("文件读取失败: " + e.getMessage());(拼字符串丢堆栈) -
❌ 冗余写法:
logger.error("文件读取失败: {}", e.getMessage(), e);(e 已含消息,重复且易错)
确认日志配置启用了堆栈输出
即使代码传了异常,如果日志 pattern 没配好,堆栈照样不显示。以 Logback 为例,确保 logback-spring.xml 或 logback.xml 中的 pattern 包含 %ex 或 %xEx:
-
%ex:标准堆栈(推荐) -
%xEx:带 MDC 上下文的堆栈(适合分布式追踪) - 错误示例:
%d %-5level [%thread] %logger{36} - %msg%n→ 缺少%ex,堆栈不会出现
高频空指针等内置异常可能被 JVM 优化掉堆栈
在生产环境高并发场景下,JVM 的 JIT 编译器会对 NullPointerExceptionIllegalArgumentException 等内置异常做“快速抛出优化”:多次触发后,复用预分配的无堆栈异常实例。
立即学习“Java免费学习笔记(深入)”;
- 现象:前几次日志有堆栈,后面只剩
java.lang.NullPointerException: null - 解决:启动 JVM 时加上参数
-XX:-OmitStackTraceInFastThrow - 注意:该参数从 JDK 6u21 起生效,对所有支持版本有效,不影响性能
需要自定义格式或脱敏时,手动获取堆栈字符串
当要存库、上报或过滤敏感路径(比如跳过 sun.* 或 java.* 的内部调用),可用 getStackTrace() + StringWriter/PrintWriter 构建:
- 不要用
e.toString()或e.getMessage()替代 - 标准写法示例:
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
logger.error("业务处理失败,堆栈如下:{}", stackTrace);



















