Java 异常处理,别让 catch 吞掉真正的现场
· 阅读需 2 分钟
Java 项目里很容易出现一种“看上去很稳”的异常处理:每一层都在 catch,每一层都在包一层自己的提示,最后用户确实看不到原始异常了,但开发排查时也很难再看到真正的现场。
2017 年我在处理一些线上问题时,对这一点的体会越来越深。
为什么异常被“处理”了,问题反而更难查
因为很多 catch 做的不是恢复,而只是吞信息。
最常见的情况是:
- 只打印一句“操作失败”
- 重新抛出新异常却不带原始上下文
- 直接返回默认值,导致问题被延后暴露
代码表面上像很周全,实际上是在把有价值的线索一层层抹掉。
我后来更愿意怎么处理异常
我不反对 catch,但更在意它到底在做什么。
如果当前层没有能力恢复问题,那更好的动作通常是:
- 保留原始异常
- 补充必要业务上下文
- 让更合适的上层统一收口
这样既不会把现场丢掉,也不会让异常一路裸奔到最顶层。
小结
Java 异常处理真正难的,不是会不会 catch,而是有没有在 catch 时保住问题现场。
对排查来说,最怕的不是异常多,而是异常被处理得“看起来没问题”。2017 年之后我越来越认同,能恢复就恢复,不能恢复就别吞。
如果一定要在中间层改写异常,我也更愿意只补业务上下文,不把原始异常链断掉。
因为真正帮助排查的,从来不只是“当前模块想表达什么”,还包括最底层到底抛了什么、在哪个条件下抛的。把这条链留住,异常信息才像证据,而不是只剩一句态度化的提示。
