业务偶发超时卡顿若与gc相关,通常是内存分配与回收节奏失配导致的瞬时stw停顿;应通过jstat抓秒级波动、gc日志比对时间戳、jmap dump堆快照结合mat分析,区分周期性/阶梯式/脉冲式三类模式精准定位。

业务偶发超时卡顿,如果和 GC 相关,往往不是持续恶化,而是“突然卡一下又恢复”,背后通常是内存分配节奏与回收行为不匹配。关键不是等超时发生再查,而是提前捕捉波动痕迹、定位触发瞬间、锁定异常对象。
看实时指标,确认卡顿是否真由 GC 引起
别只盯着监控图表的平均值,要抓秒级波动:
- 用 jstat -gc
1000 每秒刷新,重点观察:FGC 是否在卡顿时突增(哪怕只多 1 次)、YGCT 占比是否从 2% 突升到 15% 以上、老年代使用率(OU)是否在几次 YGC 后缓慢爬升又突然跳高 - 对比卡顿时间点和 jstack
输出:若大量线程堆栈停留在 java.lang.ref.ReferenceHandler、VMThread 或 GCTaskThread,基本可断定是 GC 停顿导致 - 用 top -p
查 CPU:若卡顿时 Java 进程 CPU 不高,但响应停滞,大概率是 STW 停顿而非计算瓶颈
对齐时间戳,从 GC 日志里挖出“作案时刻”
GC 日志是还原现场的关键证据,重点盯三类信息:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 触发原因:日志中括号里的关键词才是线索——比如 [GC (Allocation Failure)] 频繁出现,说明 Eden 太小或对象创建太猛;[Full GC (Metadata GC Threshold)] 则指向元空间膨胀,常见于热部署或大量动态代理
- 回收效果:某次 Full GC 后老年代使用量只从 92% → 89%,几乎没降,说明大量对象无法被回收,极可能是泄漏
- 时间锚点:把接口超时日志的时间戳(精确到毫秒)和 GC 日志逐行比对,找到最接近的一次 GC,它的前后 5 秒就是重点排查窗口
抓堆快照,用 MAT 找“赖着不走”的对象
卡顿时立刻执行,别等 OOM:
- 运行 jmap -dump:live,format=b,file=heap_$(date +%s).hprof
—— 加 live 参数能过滤掉已标记待回收的对象,更贴近真实占用 - 用 MAT 打开后,直接点 Leak Suspects Report,它常第一行就指出“1 个 com.example.OrderCache 实例占用了 68% 堆内存”
- 打开 Dominator Tree,按 Retained Heap 排序,右键可疑大对象 → Path to GC Roots → with all references,重点看是不是被 static Map、未清理的 ThreadLocal 或注册后没注销的监听器强持有
结合业务特征,区分三类偶发模式
不是所有“偶发”都一样,得看规律:
- 周期性卡顿(如每小时整点卡一次)→ 检查定时任务:报表导出、缓存预热、日志滚动是否批量 new 大量对象
- 阶梯式卡顿(第一次卡 200ms,隔两小时卡 500ms,再过几小时卡 1.2s)→ 老年代使用率缓慢上涨,典型泄漏早期,重点查静态集合、连接池、事件监听注册
- 脉冲式卡顿(某次上传大文件、反序列化万行 JSON 后立刻卡)→ 是单次请求触发的瞬时压力,需隔离优化,比如流式解析、分页加载、限制上传体积
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










