垃圾收集算法

一、常见的几种垃圾收集算法

1.1标记-清除算法

最基础的收集算法是标记-收集(Mark-Sweep)算法,该算法分为标记和清除两个阶段:首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

  • 优点:容易实现
  • 缺点:清除后会产生大量不连续的内存碎片,可能会导致之后分配较大内存时找不到足够空间,不得不提前触发另一次垃圾集
1.2复制算法

复制(Copying)算法将可用的内存分为大小相等的两块,每次只使用其中一块,当这一块用完时,就将任然存活的对象复制到另一块上,然后对已使用过的内存空间进行一次性完全清理

  • 优点:内存分配时不需考虑内存碎片的问题,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效
  • 缺点:将内存缩小为了原来的一半
1.2.1分配担保

因为新生代中的绝大多数对象的存活时间都很短,所以不需要将内存进行1:1划分,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,大小比例为8:1:1。

每次使用Eden和一块Survice空间,当回收时,将Eden和Servivor中存活的对象一次性的复制到另一块Servivor空间中。这样就只有10%的内存被“浪费”。当然,我们无法保证每次都只有10%以下的对象存活,当Servivor空间不足时,需要依赖老年代进行分配担保(Handle Promotion)。即当另一块Servivor不足以存放回收后仍存活的对象时,这些队形将直接通过分配担保进入老年代。

  • 优点:减少了内存空间的浪费
  • 缺点:当需要复制大量对象时效率会下降,需要额外的空间做担保
1.3标记-整理算法

标记-整理(Mark-Compact)算法,该算法与标记-清除算法的过程相同,但后续步骤不是对对象的直接清除,而是让所有存活的对象向内存的一端移动,然后清理掉边界外的内存。

  • 应用:主要应用于老年代
1.4分代收集算法

当前商业虚拟机的垃圾收集都采用分代收集(Generation Collection)算法,这种算法并没有什么新思想,只是根据对象存活的时间将内存分为几块。一般是将java堆分为新生代和老年代,这样可以根据不同年代的特点使用合适的收集算法。

一般来说:

  • 新生代:复制算法
  • 老年代:标记-清理算法或者标记-整理算法

发表评论

邮箱地址不会被公开。 必填项已用*标注