JVM垃圾收集算法详解

800 阅读3分钟

介绍

在JVM堆中,管理着我们几乎所有的对象,然而对象又是源源不断产生的,既然如此,那么说明JVM存在清除不需要的对象的一套算法,这些算法成为垃圾收集算法,具体的实现又称作为垃圾收集器.

标记-复制算法

首先介绍的是标记复制算法,标记复制算法是首先将内存分为大小相同的两块,比如1G的内存分为2个相等的512M的内存区域,每次只使用其中的一块,当一块区域满了后则进行垃圾回收,将存活的对象复制到另一块区域,然后再把之前使用的空间一次性清理.

优点:速度快,效率高

缺点:内存使用空间不够,每次只使用了一半内存

image.png

标记-清除算法

标记清除算法与标记复制算法有个很显著的区别,标记清除算法使用了所有内存,算法分为“标记”和“清除”阶段:可以是标记存活的对象,然后统一回收所有未被标记的对象,然后有人说,那我能不能只标记清除的对象,当然可以反过来!首先标记出所有需要回收的对象,然后在标记完成后统一回收所有被标记的对象 。这种算法虽好,但是会有两个问题:

  1. 效率问题:如果需要被标记对象非常多,那么将非常的耗时
  2. 空间问题:标记清除算法,在清除不需要的对象后会产生不连续的内存空间碎片问题,可能会导致及时内存够,部分对象也无法存放的问题.

image.png

标记-整理算法

标记整理算法也是一种标记算法,跟"标记-清除"算法步骤几乎相同,在标记过程之后并没有直接回收对象,而是让所有存活的对象往一边进行移动,然后清理掉存活对象边界以外的内存,这样减少了内存空间碎片的问题,当然效率也会差一点.

image.png

总结

当前虚拟机的垃圾收集都采用分代收集算法,只是根据对象存活周期的不同将内存分为几 块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中,每次收集都会有大量对象(近99%)死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。注意,“标记-清除”或“标记-整理”算法会比复制算法慢10倍以 上。