新生代垃圾回收算法
新生代主要存放生命周期较短的对象,其垃圾回收算法主要包括:
- 复制算法(Copying)
-
- 原理:将内存划分为等大的两块,每次只使用其中的一块。当一块内存用完了,就将还存活的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。
- 优点:解决了内存碎片化问题,且效率较高(清理内存时,记住首尾地址,一次性抹掉)。
- 缺点:内存利用率不高,每次只能使用一半内存。
- JVM实现:JVM将整个新生代按照8:1:1的比例划分为三块,最大的称为Eden区,较小的两块分别称为From Survivor和To Survivor。当Eden区满时,触发Minor GC,存活的对象被复制到From Survivor区;当再次触发Minor GC时,Eden区和From Survivor区中的存活对象被复制到To Survivor区,然后清空Eden区和From Survivor区。如此循环往复。
老年代垃圾回收算法
老年代主要存放生命周期较长的对象,其垃圾回收算法主要包括:
- 标记-清除算法(Mark-Sweep)
-
- 原理:分为两个阶段,第一阶段是标记阶段,GC会把所有的活动对象打上标记;第二阶段是把那些没有标记的对象(非活动对象)进行回收。
- 缺点:效率问题(遍历了两次内存空间),空间问题(容易产生大量内存碎片)。
- 标记-整理算法(Mark-Compact)
-
- 原理:标记阶段与标记-清除算法相同,但在清除阶段,标记-整理算法会将存活的对象都向一端移动,然后直接清理掉边界以外的内存。
- 优点:解决了标记-清除算法中的内存碎片问题。
- 分代收集算法(Generational Collection)
-
- 原理:根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清除”或者“标记-整理”算法来进行回收。