Java垃圾回收算法详解(4种Java垃圾回收算法)

Java垃圾回收算法详解(4种Java垃圾回收算法)-mikechen

Java垃圾回收算法是JVM的必备内容,也是Java面试经常考察的内容,下面我就重点详解4种Java垃圾回收算法@mikechen

 

Java垃圾回收算法详解(4种Java垃圾回收算法)-mikechen

1.标记清除算法

标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段

如下图所示:

Java垃圾回收算法详解(4种Java垃圾回收算法)-mikechen

1.标记阶段

从程序的根对象开始,递归遍历所有可以到达的对象,并将它们标记为“可达”的对象。

根对象可以是全局变量、程序的调用栈、寄存器等,在遍历的过程中,将访问到的对象打上标记。

 

2.清除阶段

遍历整个堆,将没有标记的对象,即未被标记为“可达”,视为垃圾并回收其占用的内存。

然后,在清除阶段,清除所有未被标记的对象。

 

标记清除算法优点:

最基础简单的垃圾收集算法,为后续垃圾收集算法奠定了基础,实现起来比较简单。

 

标记清除算法缺点:

  • 内存碎片:标记清除算法回收的内存是不连续的,可能会导致内存碎片问题,进而降低内存使用效率;
  • 垃圾回收效率不高:标记清除算法需要对整个堆进行遍历,因此在堆比较大的情况下,垃圾回收效率较低;
  • 扫描了整个空间两次:第一次:标记存活对象,第二次:清除没有标记的对象;

 

标记清除算法适用

标记清除算法适用于:存活对象较多的情况,比较适用于年老代。

 

2.复制算法

复制算法,如下图所示:

Java垃圾回收算法详解(4种Java垃圾回收算法)-mikechen

复制算法步骤,主要分为如下步骤:

第一步:标记出所有的存活对象

从根集合节点进行扫描,例如:线程栈中的对象、静态变量、寄存器中的指针等,标记出所有的存活对象,

 

第二步:复制对象到新内存

找出所有仍然存活的对象,并将这些存活的对象复制到一块儿新的内存,比如:上方图片下边的那一块儿绿色内存。

 

第三步:回收垃圾并被清除

当所有存活的对象都被复制到To区后,From区中的所有对象都可以被清除(图中上边的那一块儿内存)。

 

复制算法优点:

复制算法的优点是实现简单,只需要将存活对象复制到新的内存区域中即可,非常高效。

 

复制算法缺点:

需要更多的内存空间,因为JVM复制算法需要将存活对象复制到新的内存区域中,所以需要两倍的内存空间,这可能会导致内存空间的浪费。

 

复制算法适合

复制算法适合存活对象较少的情况下比较高效,基本上98%的对象是”朝生夕死”的,存活下来的会很少,所以特别适合于新生代。

 

3.标记整理算法

复制算法的高效性是建立在存活对象少的前提下,这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。

如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高,所以后面就出来了标记整理算法。

如下图所示:
Java垃圾回收算法详解(4种Java垃圾回收算法)-mikechen

标记整理算法步骤,主要分为如下4个步骤:

  1. 遍历内存中的所有对象,标记出所有正在使用的对象。
  2. 将所有标记过的对象移动到内存的一端,形成一个连续的内存块,同时将这些对象的地址更新到新的位置上。
  3. 将内存块另一端的所有未标记对象删除,并将这些内存空间标记为可用。
  4. 更新所有指向移动对象的指针,使其指向新的地址。

 

标记整理算法适合

标记整理算法适合老年代进行垃圾收集,parallel Oldgc和Serial old收集器就是采用该算法进行回收的。

 

4.分代收集算法

分代收集算法就是目前虚拟机使用的回收算法,这种算法根据对象的存活周期的不同将内存划分成几块,新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。

在JVM中,堆内存被分为三个部分:年轻代、老年代和永久代(在Java 8中,永久代被元空间所替代)。

JVM分代算法可以有效地提高垃圾回收的效率,因为不同代中对象的存活时间和存活概率不同,采用不同的垃圾回收策略可以使得垃圾回收的效率更高。

每一种JVM垃圾回收算法都会有很多不同的垃圾回收器去实现,在实际使用中,根据自己的业务特点做出选择就好。

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法