题目
如何诊断和优化频繁Full GC导致的系统卡顿问题?
信息
- 类型:问答
- 难度:⭐⭐
考点
GC原理分析,JVM参数调优,内存泄漏诊断,性能监控工具
快速回答
解决频繁Full GC问题的核心步骤:
- 使用
jstat -gcutil确认Full GC频率和内存回收效果 - 通过
-XX:+HeapDumpOnOutOfMemoryError获取堆转储文件 - 用MAT/Eclipse Memory Analyzer分析对象引用链,定位内存泄漏
- 调整JVM参数:
- 增大堆空间:
-Xmx4g -Xms4g - 优化老年代回收:
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75
- 增大堆空间:
- 代码修复:及时释放资源,避免静态集合累积数据
问题场景
某线上服务每10分钟发生一次Full GC,每次持续3秒导致请求超时。监控显示老年代占用始终高于90%。
原理说明
Full GC频繁通常由以下原因导致:
- 内存泄漏:对象被意外引用导致无法回收
- 堆空间不足:新生代存活对象过多,过早晋升老年代
- GC策略不当:CMS默认触发阈值(92%)过高
诊断步骤
1. 监控GC状态
jstat -gcutil <pid> 1000 5
S0 S1 E O M CCS YGC YGCT FGC FGCT
0.00 99.80 78.45 99.20 95.18 92.86 3200 64.512 142 186.324关键指标:
• O(老年代)持续>99%
• FGC(Full GC次数)快速增长
2. 获取堆转储
# 启动时添加参数
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dump.hprof ...3. 分析内存泄漏(MAT示例)

发现static ConcurrentHashMap累积了百万条缓存条目未释放。
代码优化示例
// 修复前:静态Map累积数据
public class CacheManager {
private static Map<String, Object> cache = new ConcurrentHashMap<>();
public void add(String key, Object value) {
cache.put(key, value); // 无清理机制
}
}
// 修复后:添加LRU淘汰策略
public class FixedCache {
private static Map<String, Object> cache = new LinkedHashMap<>(1000, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > 1000; // 限制最大条目
}
};
}JVM参数调优
# 调整后参数
java -Xmx4g -Xms4g \
-XX:NewRatio=3 \
-XX:+UseConcMarkSweepGC \
-XX:+UseCMSInitiatingOccupancyOnly \
-XX:CMSInitiatingOccupancyFraction=75 \
-XX:+ExplicitGCInvokesConcurrent参数说明:
• NewRatio=3:新生代:老年代=1:3
• CMSInitiatingOccupancyFraction=75:老年代75%时触发CMS
• 避免使用System.gc()触发Stop-The-World
最佳实践
- 监控常态化:部署Prometheus+Grafana监控GC指标
- 压测验证:使用JMeter模拟流量观察GC行为
- 分代调优:
- 年轻代:调整
-XX:SurvivorRatio避免过早晋升 - 大对象:
-XX:PretenureSizeThreshold直接进老年代
- 年轻代:调整
常见错误
- 盲目增大
-Xmx导致GC停顿时间更长 - 在容器环境未设置
-XX:MaxRAMPercentage导致超出内存限制 - 误用
-XX:+DisableExplicitGC影响NIO堆外内存回收
扩展知识
- G1 GC适用场景:堆>6G且要求稳定低延迟时,替换CMS/ZGC
- 元空间溢出:监控
Metaspace使用,设置-XX:MaxMetaspaceSize - 工具进阶:
- 飞行记录:
jcmd <pid> JFR.start duration=60s filename=gc.jfr - 线程分析:
jstack <pid> > thread_dump.txt
- 飞行记录: