GC回收算法之分代回收
GC回收垃圾主要有三个算法,分别是标记清除,复制算法以及标记整理。
三种算法各有优缺点,其中标记清除的优点就是简单高效,缺点就是很容易带来内存碎片化问题。
复制算法的话,优点确实解决了内存碎片化问题,但是同时也带来了空间利用率不高,当垃圾少,有效对象多时,效率比较低的问题。
标记整理的话,优点是解决了空间利用率的问题,缺点是还是没解决效率问题。
而分代回收则是基于上述三种回收算法的一种复合回收策略,将垃圾回收分成不同的场景,不同的场景应用不同的回收算法。下边则是对分代回收工作过程的梳理。
1.分代规则
这里是根据Java对象生命周期的长短进行划分(以老为尊),这里给对象引入了一个概念——年龄,年龄就是对象熬过GC的轮次,这句话怎么理解呢,其实就是对象经过GC可达性遍历分析当前对象还被确定为可达的轮数。
GC主要是针对堆来讲的,这里的分代将堆划分成了几个区域,分别是伊甸区、幸存区以及老年区。
其中这里的两个幸存区大小是1:1的。
2.工作流程
刚new出来的,年龄是0的对象,放到伊甸区。
熬过一轮GC,对象就放到幸存区,这里放的方法就使用的复制算法。根据经验规律,大部分Java对象生命周期都非常短,所以我们都认为能够放的下。
进入幸存区的对象也要经过GC的周期性考验,如果变成垃圾,就要被释放掉;如果不是垃圾,就会和其他不是垃圾的对象一同拷贝到另一个幸存区,这里使用的也是复制算法。因为这里的幸存区体积不大,存在一些空间浪费也能接受。
如果当前对象已经在两个幸存区之间拷贝很多次了,就进入老年代。老年代中的对象都是比较大的对象,生命周期普遍长。
多次了,就进入老年代。老年代中的对象都是比较大的对象,生命周期普遍长。
进入老年区的对象也要经过GC的周期性扫描,但是频率更低了。如果老年代的对象是垃圾了,就使用标记整理的方式进行释放。