垃圾收集算法(理论)

参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) 周志明 著

分代收集理论

一般至少会把Java堆划分为 新生代(Young Generation老年代(Old Generation 两个区域。

在新生代中,每次垃圾收集时都发现有大批对象死去,而每次回收后存活的少量对象,将会逐步晋升到老年代中存放。

在新生代用 标记-复制算法,在老年代用 标记-清理算法标记-整理算法

几个概念:

  • 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
  • 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。
  • 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
  • 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。

标记-清除算法

首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。

缺点

  • 一是 执行效率不稳定。如果Java堆中包含大量对象,而且其中大部分是需要被回收的,这时必须进行大量标记和清除的动作,导致标记和清除两个过程的执行效率都随对象数量增长而降低。
  • 二是 内存空间的碎片化问题。标记、清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

在这里插入图片描述

标记-复制算法

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

HotSpot里,考虑到大部分对象存活时间很短,将内存分为Eden和两块Survivor,默认比例为8:1:1。代价是存在部分内存空间浪费,且可能存在空间不够需要 分配担保 的情况,所以 适用于新生代

缺点

  • 如果内存中多数对象都是存活的,这种算法将会产生大量的内存间复制的开销。
  • 将内存分为两块,空间利用率不高。

在这里插入图片描述

标记-整理算法

首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

适用于老年代

缺点

  • 如果移动存活对象,尤其是在老年代这种每次回收都有大量对象存活区域,移动存活对象并更新所有引用这些对象的地方将会是一种极为负重的操作,而且这种对象移动操作必须全程暂停用户应用程序才能进行,这就更加让使用者不得不小心翼翼地权衡其弊端了,像这样的停顿被最初的虚拟机设计者形象地描述为“Stop The World”。

在这里插入图片描述