天天看点

【深入理解JVM】垃圾收集算法

标记-清除算法

普通的标记-清除算法是最基础的垃圾收集算法。分为“标记和收集两个阶段”

标记:标记出需要回收的对象,在标记完成后统一回收。标记靠的是前一文所讲的判断对象存活算法进行标记的。

清除:清除内存区域。

缺点:

  1. 效率低,标记和清除效率都不高。
  2. 空间问题: 清除后内存区域不连续,产生过多垃圾碎片,导致后续分配大对象时容易发生内存不足而触发另一次垃圾收集动作。

后续的收集算法都是标记-清除算法的升级版本,沿用了先标记后清除的思想。

复制算法

复制算法将内存区域分成两部分,每次只使用其中一部分,当一边内存用完时,将这部分对象全部复制到另一块区域,然后将该部分内存全部清除。

优点:

优化了标记-清除算法的内存碎片问题,每次垃圾收集之后得到的是一块连续的内存区域。

缺点

空间代价较大,有一半内存空间一直是空闲状态。

在JVM中的使用

应用于新生代收集算法, 新生代将内存分为一块较大的Eden和两块较小的Survivor空间,每次使用Eden和其他一块Survivor区,每当垃圾回收时,将Eden区和Survivor区中存活的对象全部复制到另一块Survivor中。最后清理掉Eden和Survivor 。

其中, Eden和Survivor的默认比例为8:1:1。 因为据研究表明,新生代中的98%对象都会在第一次就回收,所以只需要较小的空闲空间进行复制。那么特殊的情况下,Survivor空间不够时,需要依赖于堆内存中的老年代进行分配。

标记-整理算法

复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将变得低下。

标记整理算法和清除算法的流程大致相同,只是多了一步整理, 顺序是 标记-整理-清除。

整理是指,将存活对象,往内存某一端移动,移动完成后,然后将后续空间全部清除。

分代收集算法

分代收集算法只是一种思想,他是将内存区域分成多块,然后根据不同区域的特点采用不同的收集算法。

例如: 新生代对象迭代快 采用的是复制算法。老年代对象存活时间长,采用标记整理算法。

继续阅读