JVM:常用垃圾回收算法

时间:2022-01-05 11:51:28

在java内存模型中,程序计数器、虚拟机栈、本地方法栈这些区域每个线程独立拥有,与线程“同生共死”。每个栈帧内存大小是确定可知的,方法或线程结束时自动回收,这些区域不需要考虑内存回收问题。这里的垃圾回收指的是jvm堆内存和方法区的回收,这些区域内存在程序运行期间动态分配、动态回收,需要考虑选择合适的垃圾回收算法。

一、如何判断对象是否已经“消亡“

1.引用计数法

一个对象如果没有任何引用指向它,就可认为该对象已经”消亡“,这种方法有个缺点就是无法检测到引用环的存在。

2.根搜索算法(GC Roots Tracing)

通过一系列叫做”GC Roots“的对象作为起点向下搜索,走过的路径称为引用链,当一个对象到GC Roots没有任何引用链时,表明该对象已经”消亡“。

JVM:常用垃圾回收算法

左图中每个对象都存在引用链与GC Roots相连,表明对象还在,不能回收。

有图中三个对象虽然互相引用,但是没有链接与GC Roots相连,则可判断它们是可回收的对象。

二、常用垃圾回收算法

1.标记-清除算法

JVM:常用垃圾回收算法

动图展示

此算法分两段执行,mark阶段从引用根节点开始标记所有被引用的对象,寻找引用链,即仍然活着的对象。sweep阶段直接将未标记的对象清除。该算法的缺点是需要停顿整个应用(stop the world),而且容易产生内存碎片。

JVM:常用垃圾回收算法

标记清除算法:未标记的对象被清除

2.标记-复制算法

此算法把内存划分为相等大小的两个区域,每一只使用其中一个,回收过程中将存活的对象全部复制到另一个区域中,清空原区域。在年轻代中eden区和两个survivor区就是使用了此种算法。这种算法只复制存活的对象,成本较低,而且不会出现内存碎片问题,缺点是需要2倍的内存空间。

JVM:常用垃圾回收算法

标记--复制算法:只复制存活的对象

3.标记-整理算法

该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。所以,特别适用于存活对象多,回收对象少的情况下。效率比“标记-清理”算法低,但不会产生内存碎片。

JVM:常用垃圾回收算法