新生代GC采用复制算法,因其专为“朝生夕死”对象设计,每次Minor GC仅需复制约10%存活对象,配合Eden:Survivor=8:1:1三区结构与指针碰撞分配,实现无碎片、低停顿、高吞吐;而老年代因高存活率、大对象多、引用复杂,复制成本过高且需双倍空间担保,故不适用。

新生代GC采用复制算法,核心是用空间换时间,专为“朝生夕死”对象设计。它不靠标记后清理,而是把存活对象集中搬走、清空原区,天然规避碎片,分配快、停顿短——这才是它成为新生代默认策略的根本原因。
Eden + Survivor 三区结构怎么运作
HotSpot将新生代按8:1:1划分为Eden、S0(From)、S1(To)。新对象一律进Eden;Minor GC触发时,JVM扫描Eden和当前From区(比如S0),把所有存活对象复制到To区(比如S1);复制完成后,Eden和From区被整体清空,To区成为下一轮的From区,角色即时交换。
- 每次Minor GC只处理一个半区(Eden + 一个Survivor),范围可控,STW时间短
- 对象每经历一次复制,年龄+1;达到-XX:MaxTenuringThreshold(默认15)就晋升老年代
- 若To区放不下,多余存活对象直接“分配担保”进入老年代
为什么复制算法在新生代高效
IBM实测显示,98%的对象活不过一次Minor GC。这意味着每次回收只需复制极小比例的存活对象,其余90%以上内存可一键清空,远比遍历+标记+清除更轻量。
- 内存分配用指针碰撞(Bump the Pointer),无须查找空闲块,速度接近C语言malloc
- 复制后对象连续排列,后续分配不会因碎片而失败或降速
- 没有标记-清除的“浮动垃圾”问题,也没有标记-整理的移动开销
关键调优参数与实际影响
复制算法的效率高度依赖空间配比与对象生命周期分布。几个参数直接影响Minor GC频率和晋升行为:
- -XX:SurvivorRatio=8:控制Eden:Survivor比例,默认8意味着Survivor共占新生代20%,太小易导致过早晋升,太大则浪费空间
- -XX:MaxTenuringThreshold=15:不是越大越好。若应用中大量对象在第5~8次GC后才稳定,设为15会导致它们长期滞留Survivor,增加复制负担
- -XX:+AlwaysTenure(慎用):关闭年龄判断,所有存活对象直接进老年代,适合已知对象生命周期长的场景,但可能诱发老年代GC压力
什么情况下复制算法会变慢
复制算法优势的前提是“低存活率”。一旦打破这个前提,性能会明显下滑:
- 缓存类应用频繁复用对象,Survivor区内对象长期不死亡,每次GC都要复制大量数据
- 大数组或大对象直接分配在老年代(-XX:PretenureSizeThreshold),但部分被误判留在Eden,Minor GC时复制成本陡增
- Young GC过于频繁(如Eden过小),导致本该自然死亡的对象反复搬运,徒增CPU和内存带宽消耗


















