开发生涯里,最怕的不是代码写不出来,而是:本地明明能跑,发布就挂?或者 报错堆栈有一堆,到底哪一行才是我的业务代码?别慌,按我这个 SOP 一步一步来,Bug 终将无处遁形。
一、 快速定位
这是排查的第一步,目标是找到报错的那一行代码。也就是为什么不能运行,错了什么地方
通过堆栈进行倒推
拿到了异常堆栈后。
- 不要看第一行: 第一行通常是框架包装的异常。
- 要去找
Caused by: 一直往下拉,找到最下面的一个Caused by。 - 找到你写的业务包名: 在
Caused by里找com.company.biz.xxx。 - 定位到的那一行代码,就是案发现场及案发原因。
二、 深度诊断
有时候,即使找到了代码行,但也经常会还是会遇到不知道为什么会错(比如参数看着没问题,但就是莫名其妙的报错),这时候是不是已经濒临奔溃了?别慌,这时候可以用这几招。
1. 本地复现不了,只有线上有?
这个时候通常需要先看本地、线上穿惨是否一致,是不是穿参穿错了?还是本地某个服务调不通,导致和线上走了不同的逻辑?
既然代码逻辑一样,那一定是外部因素不一样。这种时候可以用环境对比法
- 查数据: 把线上的数据导一份到本地库,用本地代码跑一遍,确认是否是因为数据问题导致走了不同的逻辑。
- 查配置: 不要盲目的相信 Apollo 界面里的配置,去服务器上查内存里的值(用 Arthas 的
ognl命令直接看线上内存里的配置值)。 - 查依赖:
mvn dependency:tree,看是不是线上的 Jar 包版本和本地不一样(类冲突),不过这个对于成熟的生产项目来讲一般不太可能。
2. 代码贼长,一眼望不到头啊
很多时候即使已经定位了案发现场但由于整个办案过程长到令人发昏,经常不能快速定位到案发的事情经过
这种时候我建议可以用到一个简单的算法,即二分定位法,通过不停的拆解代码进行定位,具体可以做下面几件事情:
- 打断点/打日志: 在案发现场方法的开头、中间、结尾分别打日志
- 注释代码: (本地调试时) 把一半逻辑注释掉,看还报不报错。如果不报了,说明 Bug 在被注释的那一半里。
- 重复: 缩小范围,直到只剩下一行代码。
三、 如何正确的~~求神拜佛(~~提问)
这是很多程序员最容易忽视的一环。 提问不是单纯的“伸手”,而是一次技术交流。
1.搜索顺序
在问人之前,先过一遍这个流程:
-
搜内网 (Confluence/Wiki):
- 这是团队的知识宝库。搜一下报错关键词、业务错误码。
- 很多坑,前人踩过并在 Wiki 里留下了尸体(文档)。
-
搜公网 (Google/StackOverflow):
- 通用技术问题,大概率全球有几千人遇到过。
-
问 AI (ChatGPT/Claude):
- 把堆栈和代码扔给它,它能帮你分析出你忽略的语法或逻辑漏洞。
2.提问的艺术
如果必须向同事、导师或 AI 求助,请遵循 “最小可复现示例” 原则。
❌ 错误问法: “大佬,我的程序报错了怎么办?”(报错指的是啥?啥报错了?报的啥错?啥版本报错,只给一句话,哪怕 詹姆斯高斯林 来了也有心无力啊,要想别人帮助咱解决问题,总得知错误明细嘛)
✅ 正确问法模版:
【环境】 JDK 17, Spring Boot 2.7, MacOS
【背景】 我在做 XXX 业务,想实现 YYY 功能。
【现象】 期望输出 A,但实际输出了 B。
【报错】 核心堆栈如下:(粘贴
Caused by部分)【代码】 这是复现问题的核心代码片段:(去掉无关业务逻辑,只留关键行)
【尝试】 我尝试了方法 A(排查配置)和方法 B(断点调试),发现变量 Z 在这里变成了 null,卡住了。
对于整个报错进可能描述的详细点,给别人能帮助到咱的机会,又或者问ai也得把prompt写的完善点,好让ai理解到我们的真实问题
这样问,要帮助我们的人看一眼就能指出问题,效率翻倍
附:排查工具箱
- Arthas 线上 Debug 神器 (阿里开源),功能强大,可以参考 arthas 命令。
- Idea静态代码扫描 (提前发现 NPE),有时候多看看idea的提示能避免很多问题。
- Json.cn 格式化日志里乱七八糟的 JSON。
💡 核心心法:复现是解决的前提。 只要能在本地复现出的 Bug,就已经解决了一半; 只要能把报错信息描述清楚,就已经解决了另一半。