1、标记-清除(Mark-Sweep)算法
1、优点:实现简单,直接对内存进行标记,然后清除未标记的内存。
2、缺点: 效率问题:标记和清除两个过程都需要遍历所有对象,效率较低。 空间碎片:标记清除后会产生不连续的内存碎片,可能导致无法为大对象分配内存空间。
3、适用场景:适用于内存碎片问题不是主要关注点,且对垃圾回收效率要求不高的场景。
2、复制(Copying)算法
1、优点: 没有内存碎片:复制算法将内存划分为等大的两块,每次只使用其中一块,因此不会产生内存碎片。 适用于新生代:新生代中对象存活时间短,复制算法简单高效。
2、缺点: 内存利用率低:由于每次只使用一块内存,因此内存利用率只有50%。 复制开销:当存活对象较多时,复制的开销会增大。
3、适用场景:适用于新生代,因为新生代中对象存活时间短,且对象数量相对较少。
3、标记-整理(Mark-Compact)算法
1、优点: 消除内存碎片:在标记清除的基础上,通过整理操作使存活对象连续排列,从而消除内存碎片。 适用于老年代:老年代中对象存活时间长,内存碎片问题较严重,标记整理算法可以很好地解决这一问题。
2、缺点: 效率略低:相对于复制算法,标记整理算法需要移动存活对象,因此效率略低。
3、适用场景:适用于老年代,以及需要解决内存碎片问题的场景。
4、分代收集(Generational Collection)算法
1、优点: 根据对象存活周期的不同将内存划分为几块,提高了垃圾回收的效率。 新生代使用复制算法,老年代使用标记整理算法,结合了不同算法的优点。
2、缺点: 实现复杂:需要维护多个内存区域,增加了管理的复杂性。
3、适用场景:适用于大多数Java应用程序,特别是那些对象存活周期差异较大的场景。