Java中的分代垃圾回收机制详解
字数 1256 2025-11-07 22:15:37
Java中的分代垃圾回收机制详解
一、分代假说与设计理念
- 弱分代假说:绝大多数对象都是朝生夕死的,生命周期很短
- 强分代假说:经历越多次垃圾回收仍然存活的对象,越不可能成为垃圾
- 基于这两个假说,JVM将堆内存划分为不同代(Generation),采用不同的回收策略
二、内存分代结构
堆内存划分为三个主要区域:
-
新生代(Young Generation)
- Eden区:新创建的对象首先分配在这里
- Survivor区(两个):From Survivor和To Survivor,存放Minor GC后存活的对象
- 默认比例:Eden:From:To = 8:1:1
-
老年代(Old Generation)
- 存放长期存活的对象
- 大对象也可能直接分配在老年代
-
元空间(Metaspace,JDK8+)
- 替代永久代,存放类元数据信息
三、对象分配与晋升流程
-
新对象优先在Eden区分配
-
当Eden区满时,触发Minor GC:
a) 标记Eden和From Survivor中的存活对象
b) 将存活对象复制到To Survivor区
c) 清空Eden和From Survivor
d) 交换From和To Survivor的角色 -
对象晋升老年代的条件:
- 年龄阈值:对象在Survivor区经历一定次数(默认15)Minor GC后仍存活
- 大对象直接进入老年代
- Survivor区中相同年龄的对象总大小超过Survivor空间一半时,年龄≥该年龄的对象直接晋升
四、垃圾回收类型
-
Minor GC/Young GC
- 只回收新生代
- 采用复制算法,停顿时间短
- 触发条件:Eden区空间不足
-
Major GC/Old GC
- 只回收老年代
- 通常与Full GC混淆,但实际指代老年代回收
-
Full GC
- 回收整个堆,包括新生代、老年代、元空间等
- 停顿时间较长,应尽量避免频繁发生
- 触发条件:老年代空间不足、元空间不足、System.gc()调用等
五、垃圾回收算法组合
-
新生代:复制算法
- 优点:没有内存碎片,效率高
- 缺点:浪费一部分内存空间
-
老年代:标记-清除或标记-整理算法
- 标记-清除:产生内存碎片但速度快
- 标记-整理:避免碎片但需要移动对象
-
常见组合:
- Serial + Serial Old:单线程,适合客户端应用
- Parallel Scavenge + Parallel Old:吞吐量优先
- ParNew + CMS:低延迟,响应时间优先
- G1:分区收集,可预测的停顿时间
六、相关JVM参数
- -Xms/-Xmx:堆初始大小/最大大小
- -XX:NewRatio:老年代与新生代的比例
- -XX:SurvivorRatio:Eden与Survivor的比例
- -XX:MaxTenuringThreshold:对象晋升老年代的年龄阈值
- -XX:+PrintGCDetails:打印GC详细日志
七、优化建议
- 根据应用特性调整各代比例
- 避免创建过大对象数组
- 合理设置堆大小,避免频繁Full GC
- 选择适合应用场景的垃圾收集器