什么是分代垃圾回收?它是如何工作的?代码举例讲解

分代垃圾回收是基于对象存活周期的垃圾回收算法。Java虚拟机将堆内存划分为新生代和老年代,根据不同的垃圾回收算法对不同代进行回收。
新生代:存放刚刚创建的对象,每次垃圾回收时会回收大部分对象。
老年代:存放在新生代通过垃圾回收演变来的对象,垃圾回收频率低。

分代垃圾回收的工作原理:

  1. 大部分对象在新生代中快速死亡,每次GC会回收大量对象,新生代的内存利用率较低。
  2. 新生代内存使用达到一定比例时,Minor GC会对新生代进行垃圾回收。
  3. 对象在新生代SURVIVE若干次GC后,会被放入老年代。
  4. 老年代对象死亡速度慢,垃圾回收频率较低,内存利用率较高。
  5. 当老年代使用达到一定比例时,Major GC会对整个堆进行垃圾回收。
  6. 老年代对象数量过多时,会使用” remembered set “记录新生代中引用老年代对象的关联,加速Major GC。

应用分代收集算法的主要垃圾回收器有:
Parallel Scavenge收集器:新生代收集器,Minor GC使用复制算法。
CMS收集器:老年代收集器,Major GC使用标记清除算法。
G1收集器:将堆内存划分为多个区域,按新生代和老年代方式进行回收。

来看一个简单例子:

public class GCDemo {
    public static void main(String[] args) {
        byte[] data1 = new byte[2*1024*1024];  // 新生代2MB

        data1 = null;     // 一次Minor GC,data1可回收

        byte[] data2 = new byte[2*1024*1024];  // 经历过Minor GC,放入老年代

        data2 = null;     // 老年代对象,下次Major GC可回收
    }
} 

执行该程序:

  1. 分配2MB新生代对象data1,此时新生代已满,触发Minor GC,data1被回收。
  2. 分配2MB新生代对象data2,data2经过Minor GC存活,会被晋升到老年代。
  3. data2变为不可达,要等到下次Major GC才会被回收。