垃圾回收原理(通俗版)

垃圾回收原理

一、GC是什么

场景类比:

​ 你的家 = JVM内存

​ 家具物品 = Java对象

​ 保洁阿姨 = 垃圾收集器

打扫过程:

1. 识别垃圾:阿姨检查哪些是真垃圾(没人用的对象),哪些是还要用的(被引用的对象)
2. 分区打扫:
 	1. 客厅(新生代):每天打扫,速度快,但只收拾表面垃圾
 	2. 储藏室(老年代):每周大扫除,时间长,但收拾得彻底
 	3. 书房(元空间):存放重要文件,很少清理

二、GC核心原理:三部曲

第一步:找垃圾--谁没人要了

关键算法:

  • 引用计数:数一数多少个人指着这个对象说 我要
  • 可达性分析:从祖宗对象出发,能找到的就是有用的

第二步:收垃圾--怎么收拾

  1. 新生代打扫法
    1. 把还要的家具搬到隔壁房间(Survivor区)
    2. 把不要的家具扔掉(清理Eden区)
    3. 来回版几次还用的家具,搬到储藏间(晋升到老年代)
  2. 老年代打扫法
    1. 标记-整理:把所有要的家具靠墙放好,中间空出来
    2. 标记-清除:直接把不要的家具扔掉(有碎片)

第三步:倒垃圾--空间再利用

清理出来的空间,就像腾出的空地,可以放新家具(新对象)

三、GC性能瓶颈(哪里会卡住)

瓶颈1:STW(stop the world)- 全员暂停

保洁阿姨打扫时喊:"所有人停下!不许动!"
程序暂停 → 用户觉得卡顿

表现:应用响应变慢,请求超时

瓶颈2:频繁Minor GC - "老喊暂停"

客厅太小,刚打扫完又乱了
导致:阿姨每分钟都要喊一次暂停

原因:新生代空间太小或对象创建太快

瓶颈3:Full GC太久 - "大扫除时间太长"

储藏室东西太多,阿姨打扫要1小时
这期间全家人都得等着

常见原因

  1. 老年代空间不足
  2. 内存泄漏(东西只进不出)
  3. 大对象直接进老年代

瓶颈4:内存碎片 - "空间浪费"

储藏室:有空位但放不下新家具
因为位置太分散,每个空位都很小

影响:明明有空闲内存,却说内存不足

瓶颈5:错误的GC策略--用错保洁阿姨

需要快速响应时请了慢工出细活的阿姨
需要省电时请了动作快但费力的阿姨

匹配问题

  • Web应用 → 需要低延迟(CMS、G1、ZGC)
  • 批处理 → 需要高吞吐量(Parallel GC)

四、场景问题场景

案例1:电商秒杀

问题:瞬间创建大量订单对象
表现:频繁Young GC,CPU飙升
解决:增大年轻代,使用G1收集器

案例2:后台报表系统

问题:生成大报表对象
表现:老年代快速填满,频繁Full GC
解决:增加老年代大小,调整晋升阈值

案例3:缓存服务

问题:缓存对象长时间存活
表现:老年代占用高,Minor GC效率低
解决:使用CMS或G1,减少STW时间

五、优化思路

原则1:让对象尽快死掉

// 不好:对象活太久
List<String> cache = new ArrayList<>(); // 一直引用

// 好:及时释放
{
    List<String> temp = new ArrayList<>();
    // 用完后自动回收
}

原则2:选择合适的“保洁阿姨”

  1. 场景:小应用 推荐GC:Serial GC 特点:单线程,简单
  2. 场景:后台计算 推荐GC:Parallel GC 特点:吞吐量优先
  3. 场景:web服务 推荐GC:G1 GC 特点:平衡吞吐和延迟
  4. 场景:大内存 推荐GC:ZGC/Shenandoah 特点:超低延迟

原则3:合理分配“房间大小”

# 常用参数
-Xms4g -Xmx4g        # 总堆大小
-XX:NewRatio=2       # 老年代:新生代=2:1  
-XX:SurvivorRatio=8  # Eden:Survivor=8:1:1

六、监控和诊断(怎么发现问题)

1、看症状:

​ 应用卡顿----》可能full GC

​ CPU一直高 ---》可能频繁GC

​ 内存增长不停 ---》可能内存泄漏

2、用工具

# 查看GC情况
jstat -gcutil <pid> 1000

# 生成堆快照
jmap -dump:format=b,file=heap.hprof <pid>

# 实时监控
jvisualvm  # 图形化工具

3、关键指标

  • GC频率:多久一次?
  • GC时间:每次停多久
  • 吞吐量:GC时间/总时间 < 5%
  • 停顿时间:单次停顿< 1000ms

总结:

GC就像打扫卫生,太频繁打扫影响生活(性能差),太久不打扫房子乱了(内存溢出),大扫除太久全家等待(卡顿)。关键是要让垃圾早点产生(对象及时释放),分区打扫(年轻/年老代分开),选对保洁员(合适的GC算法),监控清洁效果(看GC日志)。没有最好的GC,只有合适的GC。

posted @ 2026-01-30 16:24  hqq的进阶日记  阅读(3)  评论(0)    收藏  举报