核心是直接传异常对象作为最后一个参数,如logger.error("msg", e),框架自动输出完整堆栈;避免字符串拼接或调用getMessage();同时logback.xml中pattern需含%ex或%xEx。

直接传异常对象给日志方法,别拼字符串,也别只取 getMessage()——这是最核心的一点。堆栈信息不是“额外内容”,而是诊断异常的唯一路径,丢掉它等于把错误现场抹掉。
用 logger.error("提示", e) 而不是拼接字符串
主流日志框架(SLF4J、Logback、Log4j2)都支持带 Throwable 参数的重载方法。只要把异常对象作为最后一个参数传进去,框架会自动展开完整堆栈(含 cause 链、suppressed 异常等)。
- ✅ 正确:
logger.error("文件读取失败", e); - ✅ 带占位符也正确:
logger.error("用户 {} 操作失败, ID={}", username, userId, e); - ❌ 错误:
logger.error("文件读取失败: " + e.getMessage());—— 堆栈彻底丢失 - ❌ 错误:
logger.error("失败", e.toString());—— 只有类型+消息,无堆栈 - ❌ 错误:
logger.error("失败: {}", e);——e被当普通参数,框架无法识别为异常
检查日志输出格式是否启用堆栈渲染
即使代码传对了,如果日志配置没打开堆栈输出,依然看不到。关键看 pattern 中有没有 %ex 或 %xEx:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- Logback 中,确保
包含%ex(推荐)或%xEx(带 MDC 上下文) - 默认
%ex只展开第一层异常;若需深层 cause(如 SQLException 套 IOException),改用%ex{5}指定最大深度 - Log4j2 对应的是
%throwable{full},不是%ex,混用会导致堆栈不显示
警惕 JVM 的“快速抛出优化”导致堆栈消失
高并发下,JVM(JDK 6u21+)会对 NullPointerException、IllegalArgumentException 等内置异常做优化:复用无堆栈的预分配实例。
- 现象:前几次日志有堆栈,后续只剩
java.lang.NullPointerException: null - 解决:JVM 启动参数加上
-XX:-OmitStackTraceInFastThrow - 该参数不影响性能,且对所有支持版本有效
需要脱敏或自定义时,手动构造要谨慎
仅在必须过滤路径(如跳过 sun.*)、截取层数或存库上报时才手动处理堆栈:
- 用
e.getStackTrace()获取数组,配合StringWriter+PrintWriter构建字符串 - 避免用
e.toString()或Arrays.toString(e.getStackTrace())—— 格式混乱、无缩进、漏 cause - 切勿在日志语句里拼接堆栈字符串:既破坏可解析性,又丢失 MDC 上下文(如 traceId)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










