分代收集算法通过对象生命周期预判优化性能:年轻代用复制算法高效清理短命对象,老年代用标记-整理避免碎片,配合监控调参实现可控gc。

分代收集算法的性能优化,核心在于它抓住了一个关键事实:绝大多数对象“朝生暮死”。不是靠堆得大、扫得勤,而是靠对对象生命周期的合理预判,把回收工作拆解到最该发力的地方。
年轻代用复制算法,快准狠地清理短命对象
新创建的对象默认进入Eden区。一旦Eden满,就触发Minor GC——只扫年轻代,不碰老年代。此时JVM只需标记出存活对象,全部复制到一个Survivor区(比如S0),Eden和另一个Survivor(S1)直接清空。这种复制方式几乎没有遍历开销,也不产生碎片。
- 复制成本低:每次Minor GC后,90%以上的对象被直接丢弃,只需搬运少量存活者
- 内存连续:复制后目标Survivor区天然紧凑,下一次分配无需查找空闲块
- 晋升控制:对象在Survivor间来回复制(每过一次GC算1岁),达到阈值(如15次)才进老年代,避免过早堆积
老年代用标记-整理,稳住长周期对象的内存布局
老年代存放的是撑过多次Minor GC的“资深对象”,它们存活率高、变动少。这里不适合频繁复制,但又不能容忍碎片——否则大对象分配失败会触发代价高昂的Full GC。
- 标记-整理兼顾效率与空间:先标记所有存活对象,再把它们向内存一端压缩,腾出大片连续空间
- 减少Full GC频率:只要老年代碎片可控,就不会因“明明有空间却分不出一块给大对象”而被迫整堆扫描
- 配合晋升策略:合理设置晋升年龄或老年代占用阈值(如-XX:MaxTenuringThreshold、-XX:PretenureSizeThreshold),能进一步平滑GC压力
分代假设不是凭空而来,而是可验证、可调优的工程实践
所谓“大部分对象很快不可达”,在真实业务中并非玄学。通过开启GC日志(-Xlog:gc*)并用工具分析,你能看到Eden区每次回收的存活率、对象晋升节奏、老年代增长速度等数据。这些数字决定了你是否该调大年轻代(减少Minor GC次数)、缩小Survivor比例(避免复制浪费),或者启用G1/ZGC来弱化分代边界。
- 监控是前提:jstat -gc
可实时查看各代使用率和GC耗时 - 调参有依据:-XX:NewRatio=2 表示年轻代:老年代 = 1:2;-XX:SurvivorRatio=8 表示Eden:S0:S1 = 8:1:1
- 不追求绝对最优:不同应用负载差异大,分代策略需结合吞吐量、延迟、内存容量综合权衡
分代收集不是把堆简单切几刀,而是用对象行为建模驱动内存管理。它让“高频小扫”和“低频精整”各司其职,把GC从不可控的全局震荡,变成可预期、可干预的系统级调控。











