17 GC在各个分代中的作用

vvEcho 2026-03-12 11:59:02
Categories: Tags:

了解上面的内容,我们需要先了解JVM中堆的分代的结构

堆的分代结构

      JVM Heap
         │

┌─────────┴─────────┐
│ │
新生代 (Young) 老年代 (Old)

Eden + Survivor

S0 + S1(Survivor区分为S0和S1,为了方便复制)

Eden : S0 : S1 = 8 : 1 : 1

新生代GC

新生代主要使用 复制算法(Copying GC)。
流程如下:新建对象-》eden区 -》eden区满-》触发YoungGC-》此时jvm会将survivor From复制到Survivor To;并且这个时候会清空eden区的对象和s0区,然后s0 s1交换角色;

对象晋升到老年代

每一次youngGC,幸存的对象年纪就会加1,当大于等于默认的15次时就会移动到老年代
-XX:MaxTenuringThreshold=15

如果突然有个大对象,导致survivor区满,此时对象会从eden区移动到old区,也称为空间分配担保

老年代GC

老年代对象存活时间更长,因此使用不同算法。
1.标记清除算法(Mark-Sweep)
2.标记整理算法(Mark-Compact)

为什么需要S0和S1?

新生代采用复制算法进行垃圾回收,需要两个 Survivor 区作为 From 和 To。
GC 时将 Eden 和 From 中存活对象复制到 To,然后清空 Eden 和 From,再交换 S0 和 S1 的角色,从而避免内存碎片并提高回收效率

为什么 Eden:S0:S1 = 8:1:1?

JVM 统计发现绝大多数对象生命周期很短,90% 对象在第一次 GC 就会被回收。
因此需要一个较大的 Eden 区减少 Minor GC 频率,而 Survivor 只需要容纳少量存活对象即可。
8:1:1 是 HotSpot 在大量实践中得到的较优比例,既能提高内存利用率,又能减少 GC 次数