分代垃圾收集步骤
首先,大部分新对象(不是所有对象,因为大对象可能直接被分配到老年代)都被分配到Eden空间。两个Survival空间开始时都是空的。
当Eden空间被填满时,会触发次要垃圾回收。
被引用的对象被移动到第一个Survival空间,Eden空间被清空,未被引用的对象因此被删除。
在下一次次要 GC 中,Eden空间也会发生同样的事情。未被引用的对象被删除,被引用的对象被移动到Survival空间。然而,在这种情况下,它们被移动到第二个Survival空间(S1)。此外,来自第一个survival空间 (S0) 上的上一次次要 GC 的对象又获得一次被回收的机会,存活下来的对象的年龄会增加并被移动到 S1。一旦所有幸存的对象都被移动到 S1,S0 和 eden 都被清除。注意我们现在在survial空间中有不同年龄的对象。
在下一次次要 GC 中,重复相同的过程。然而这次survival空间发生了变化。被引用的对象被移动到 S0。幸存的对象年龄增加。 Eden 和 S1 被清除。
在minor GC之后,当年老的对象达到一定的年龄阈值(本例中为8)时,它们会从年轻代提升到老年代。
随着minor GC的不断发生,对象会不断被提升到老年代空间。
最终,将对老年代执行主要 GC,清理并压缩该空间。
需要指出的是,在次要垃圾回收期间,不能保证分配的survival空间总是足够大以容纳来自Eden空间和其他survival空间的幸存对象。如果溢出了,剩下的需要被疏散的对象就会被移到老年代。这被称为过早提升(premature promotion)。它会导致年轻对象进入老年代并助长老年代的增长,这会导致严重的性能问题。
此外,如果在次要垃圾回收期间老年代变满并且无法将更多对象复制到其中,那么次要垃圾回收通常会在次要垃圾回收之后进行完整垃圾回收,它会收集整个 Java 堆。这称为提升失败。