组里有个跑了大半年的 Spring Boot 订单服务,最近两周开始出现一个诡异的问题:每天早上 10 点左右,JVM 堆内存就飙到 90% 以上,GC 频率从几分钟一次变成几十秒一次,偶尔直接 OOM 重启。之前同事用 jstat 和 jmap 看过几次,没找到泄漏点,事情就一直拖着。
做了四五年 Java 后端,内存泄漏这种问题不是没见过,但每次都挺头疼的——Heap Dump 几十个 G,MAT 打开慢得要死,分析起来全靠经验猜。这次正好在试用 TraeCode,就想着能不能让 Agent 帮忙一起排查,看看 AI 在性能调优这块到底能帮到什么程度。
第一步:把报错日志和 GC 日志丢给 Agent
我没有一上来就让 TraeCode 帮我"修 bug",而是先把两周的 GC 日志(-Xloggc 输出的)和几次 OOM 前后的应用日志整理成一个文本文件,直接丢进对话里,跟 Agent 说:
“这是一个 Spring Boot 2.7 + JDK 11 的订单服务,最近两周每天早上 10 点左右堆内存飙到 90%+,GC 频率异常。这是 GC 日志和应用日志的关键片段,帮我分析一下内存增长的模式。”
Agent 看完日志后,直接指出几个关键信息:
- Full GC 频率从正常的 4 小时一次,恶化到 20 分钟一次
- 每次 Full GC 后老年代回收率从 60% 逐步降到 15%,说明有对象持续堆积且无法回收
- 内存增长曲线不是突增而是缓慢爬升,更符合慢性泄漏的特征
这一步省了我至少半小时手动翻日志的时间。
第二步:让 Agent 帮忙分析 Heap Dump
我用 jmap 导了一份 Heap Dump(大概 3G),用 MAT 的 Top Consumers 导出了一份 CSV(包含占用内存最大的 50 个类)。把 CSV 丢给 TraeCode:
“这是 MAT 导出的 Top Consumers 数据,帮我看看哪些类的实例数量和内存占用不正常,重点排查跟订单业务相关的类。”
Agent 很快锁定了两个可疑点:
com.xx.order.model.OrderContext实例数 47 万+,占用堆内存 1.2G,但这个类按理应该是请求级别的短生命周期对象java.util.concurrent.ConcurrentHashMap$Node实例数 120 万+,其中大部分 key 是 UUID 格式字符串
Agent 推测:某个地方把本该回收的 OrderContext 对象塞进了一个全局的 Map 里,而且 key 是 UUID,很可能是某种"会话缓存"或者"分布式事务上下文"之类的东西。
第三步:定位代码 + 修复
有了方向,我直接在 TraeCode 里打开项目,用 SOLO 模式让它搜代码:
“在项目中搜索所有引用了 OrderContext 的地方,特别是把它 put 进 Map、List、Cache 的代码。重点关注 @Component、@Service 这种单例 Bean 里的成员变量。”
Agent 扫了一遍代码,10 秒钟就找到了问题根源——一个 OrderStateMachineService(@Service 单例),里面有一个 ConcurrentHashMap<String, OrderContext> pendingOrders,用来存储"待处理"的订单上下文。问题是这个 Map 只有 put 没有 remove,订单处理完后没人清理。
更离谱的是,这个 Map 还没有设置过期策略,也没有定时清理任务。服务跑了大半年,积累的订单上下文越来越多,直到内存撑不住。
修复方案也很简单:
- 订单处理完成后立即 remove
- 加一个
@Scheduled定时清理超过 30 分钟的过期条目 - 把 ConcurrentHashMap 换成 Caffeine Cache,设置 maximumSize 和 expireAfterWrite
改完跑了一天,内存曲线稳得像一条直线,Full GC 恢复到 4 小时一次。
最后做成什么
- 定位了一个隐藏大半年的内存泄漏,根因是单例 Bean 里的 ConcurrentHashMap 只进不出
- 修复代码不到 20 行,加了清理逻辑 + 换成 Caffeine Cache
- 整个过程从分析日志到定位代码到修复,大概花了 2 个小时。之前同事手动排查了两次都没搞定,每次花半天最后没结论
几个体会
- Agent 不会替你思考,但能帮你快速缩小范围。比如 47 万个 OrderContext 实例这种信息,人眼翻 MAT 报告很容易忽略,但 Agent 一眼就能看出"这个类的实例数量不正常"
- 日志和数据分析是 TraeCode 最擅长的场景之一。你不需要自己写脚本去 parse GC 日志,直接把原始数据丢给它就行
- 代码搜索这块 SOLO 模式很好用,比 IDE 的全局搜索更智能——它不是简单的关键词匹配,而是理解你的意图去找相关代码


