答案是排查java内存问题需遵循“先保服务、再留证据、后定位根因”原则:紧急止损摘节点/降级/扩容;现场取证必取gc日志、堆快照、线程快照;根因定位分四类——内存泄漏、类加载泄漏、新生代过小、大对象直入老年代;落地优化按代码→jvm→架构优先级推进。

直接上手排查,核心是“先保服务、再留证据、后定位根因”,不能一上来就重启或调参。
紧急止损:别让系统彻底卡死
Full GC 频繁时,应用线程会 Stop-The-World,接口超时、吞吐暴跌是必然现象。第一反应不是分析,而是稳住业务:
- 立刻从负载均衡摘除问题节点,避免雪崩扩散
- 若支持降级,关闭非核心功能(如统计上报、日志采样、异步通知)
- 临时扩容实例分担流量,缓解单节点压力
- 切忌直接重启——除非已完整采集现场数据,否则所有内存线索将永久丢失
现场取证:三类关键数据必须在重启前拿到
所有诊断都依赖这三份原始数据,缺一不可:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
GC 日志:用
jstat -gcutil <pid> 1000</pid>实时观察,重点关注OU(老年代使用率)是否持续 >85%、FGCT(Full GC 总耗时)是否占运行时间 10% 以上;若未开启日志,立即执行并重定向保存 -
堆快照:执行
jmap -dump:live,format=b,file=heap.hprof <pid></pid>(加live参数可减少暂停时间);目标是老年代快满但还没 OOM 时 dump,此时泄漏对象最典型 -
线程快照:用
jstack <pid> > jstack.log</pid>查看是否有大量线程阻塞、死锁,或某类任务(如定时批量任务)正在密集创建对象
根因定位:四类高频原因对应不同线索
根据 GC 日志和堆快照交叉验证,快速归类:
-
老年代缓慢上涨 → 内存泄漏:MAT 中看 “Leak Suspects” 报告,重点查
static集合、未注销监听器、ThreadLocal 残留、缓存未设淘汰策略 -
元空间(Metaspace)持续增长 → 类加载泄漏:日志出现
Metaspace allocation failure;检查动态代理(如 Spring AOP)、热部署框架、频繁 new ClassLoader 的代码 -
Eden 区秒空、Survivor 区几乎不回收 → 新生代太小:对象来不及在年轻代被回收就晋升老年代,jstat 显示
YGC极其频繁且S0/S1使用率长期接近 0 或 100% -
大对象直入老年代 → 代码层问题:MAT 中发现大量
byte[]、char[]或第三方库的大缓存对象;对应代码通常是每次请求构造 MB 级缓冲区、JSON 序列化大结果集等
落地优化:按优先级推进修复
修复顺序应与影响程度匹配,避免盲目调参:
- 先改代码:清理静态缓存、补全资源关闭逻辑、限制缓存大小、复用大对象(如用对象池管理 byte[] 缓冲区)
- 再调 JVM:确认无泄漏后,调整
-Xmn增大新生代,设置-XX:MaxGCPauseMillis启用 G1 收集器,合理设定-XX:MetaspaceSize - 最后看架构:若问题随特定批量任务触发,考虑拆分任务粒度、增加限流、引入异步队列削峰
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










