(11)《GC调优 》

2026-03-21
4
-
- 分钟
|

1. 什么是 GC?

  • GC(Garbage Collection):JVM 自动回收不再使用的对象内存,避免内存泄漏。
  • 程序员不用手动释放内存,JVM 帮你“打扫垃圾”。

2. 堆内存结构(GC 主战场)

堆 = 新生代(Young Gen) + 老年代(Old Gen)

  • 新生代:新创建的对象先放这里。又分为:
    • Eden 区:对象出生地。
    • Survivor S0 / S1:幸存者区,用于存放经过一次 GC 还活着的对象。
  • 老年代:长期存活的对象最终移入这里。

💡 类比:新生代像“幼儿园”,老年代像“养老院”。


3. 常见 GC 算法

算法特点适用区域
标记-清除(Mark-Sweep)标记活对象,清除死对象;会产生碎片老年代
复制(Copying)把活对象复制到另一块空间,清空原空间;无碎片但浪费内存新生代
标记-整理(Mark-Compact)标记后把活对象“挤”到一端,再清理边界外老年代

4. 常见 GC 收集器(JDK 8 为主)

收集器类型特点适用场景
Serial单线程简单高效,STW(Stop-The-World)单核/小内存
ParNew多线程版 Serial配合 CMS 使用中小型应用
Parallel Scavenge + Parallel Old吞吐量优先最大化 CPU 利用率后台计算、批处理
CMS(Concurrent Mark Sweep)低延迟并发执行,减少停顿Web 应用(已废弃)
G1(Garbage First)分区+并发可预测停顿时间,兼顾吞吐与延迟大堆(>4GB)、低延迟要求
ZGC / Shenandoah超低延迟停顿 <10ms,JDK11+(实验),JDK15+(正式)极致响应要求

✅ JDK 8 推荐:G1(堆 > 4GB)或 Parallel(追求吞吐)


5. GC 触发时机

  • Minor GC:Eden 区满 → 清理新生代(快,频繁)
  • Major GC / Full GC:老年代满 or 元空间满 → 清理整个堆(慢,应尽量避免)

⚠️ Full GC 会导致长时间 STW,严重影响性能!


6. 关键调优目标

目标说明
降低 Full GC 次数通过合理分配堆大小、调整对象晋升年龄等
控制 GC 停顿时间选择合适收集器(如 G1)
提高吞吐量减少 GC 时间占比(如用 Parallel)

7. 常用 JVM 参数(JDK 8 示例)

# 堆大小
-Xms4g -Xmx4g          # 初始 & 最大堆(建议设为相同,避免动态扩容)

# 新生代大小
-Xmn2g                 # 新生代大小(一般为堆的 1/3~1/2)

# 选择 GC
-XX:+UseG1GC           # 使用 G1
-XX:+UseParallelGC     # 使用 Parallel(默认)

# G1 调优
-XX:MaxGCPauseMillis=200   # 目标最大停顿时间(毫秒)
-XX:G1HeapRegionSize=16m   # Region 大小(可选)

# 打印 GC 日志(排查必备)
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:/path/to/gc.log

8. 调优步骤(实战流程)

  1. 监控:用 jstat -gc <pid> 或 GC 日志观察 GC 频率、停顿时间。
  2. 分析
    • Minor GC 频繁?→ Eden 太小 or 对象太多。
    • Full GC 频繁?→ 老年代不够 or 内存泄漏。
  3. 调整
    • 增大堆 or 调整新生代比例。
    • 切换更合适的 GC 收集器。
  4. 验证:压测 + 观察 GC 日志是否改善。

9. 小贴士(避坑指南)

  • 不要盲目调大堆:堆越大,GC 停顿可能越长(除非用 G1/ZGC)。
  • 避免内存泄漏:静态集合、未关闭资源等会导致对象无法回收。
  • 生产环境务必开 GC 日志:这是诊断性能问题的“黑匣子”。

🌟 记住:GC 调优不是“一次搞定”,而是“监控 → 分析 → 调整 → 验证”的循环过程。


✅ 本笔记覆盖 GC 核心概念、算法、收集器、参数、调优方法,语言通俗,适合快速掌握和复习。

评论交流

文章目录