jvm垃圾回收算法

134 阅读4分钟

我们就说最常用的三个垃圾回收算法。

  • 1.标记清除
  • 2.标记复制
  • 3.标记整理、

中间进行个小插曲,垃圾回收算法的前置知识,我们要知道如何判断哪个对象是垃圾。

这里有两个方法,一个是引用计数器法,一个是可达性分析算法。

1.引用计数器法

引用计数器法就简单说说,这个方法并不是java所采用的。所谓引用计数器发,就是一个对象被一个变量引用了一次,计数就加1。当取消对这个对象的引用计数就会减1。当计数为0时,代表此对象就是垃圾。但这个方法有个弊端,就是产生对象之间的循环引用,导致本来是垃圾的对象,并不能及时被清楚。

2.可达性分析算法

这种算法,就是Java所采用的。这种的实现方式就和引用计数器,不同。引用计数器可以看作是把对象实例为中心,记录该对象被引用的次数。而可达性分析算法把重心放在了对象实例的引用上。也就是Gcroot。然后根据gcroot,查找gcroot所引用的对象。当没有被gcroot所引用的对象,此时就是垃圾。

那么哪些可以作为gcroot呢。

  • 栈中局部变量表中的变量
  • 方法区中的静态变量
  • 方法区中的常量
  • 本地方法JIN对象的引用

说明下,gcroot对象不是堆中那个实例对象。事实例对象的引用作为gcroot

标记清除

概念

经过上面的如何进行垃圾的辨别,有了初步认识,现在来解析这些算法,就容易多了。标记清除,顾名思义,首先会通过gcroot进行查找对象,并标记。当对象中的属性也引用了另一个对象,也会进行标记。最终该gcroot形成一个链该链上的对象都是可达的。而那些没有被链起来的对象,就是不可达的。也就是垃圾。此时如果发生gc就会 清除那些并没有被标记的垃圾对象。

光文字描述可能会有很多不理解。接下来附上图。

优点嘛:其实也没啥优点。时间上:标记的时候要遍历一遍,清理的时候也要遍历一遍。哈哈哈。没啥优点。空间上嘛:看下条缺点。

缺点嘛:看图也能很明显的看出来,碎片化严重啊。可能总体内存还有很多,但是是分散的。如果这时出现个大对象,也放不下啊。

标记复制

概念

和上面有所不同。首先这个算法,需要至少两个内存区域。这里我们假设A区B区,首先对象创建在A区,当第一次gc时,会标记A区中的可达性对象。把A区中所有的可达性对象全部复制到B区。再把A区的对象全部删除。下一次就同样的操作,把B区的复制到A区。

图例:

优点:由于上面的标记清除算法在效率上十分低,这个算法优化了这一点。只需要遍历一遍,进行标记操作,之后进行复制,然后全部清除之前的。

缺点:缺点也很明显。需要更多了内存来进行对象的迁移。造成内存上开销更大

标记整理

概念

这个算法,其实和第一个标记清理差不多。多了一个整理的过程。也是一样的进行对可达对象进行标记,然后进行清除。最后多了一个步骤,对清除后的内存空间进行整理。也就避免了第一种的内存碎片化问题。

上图:

优点:优点嘛,就是相对于第一种,来说。对空间进行整理,避免内存碎片化问题。进而防止,内存不能存储大对象而再次进行gc的问题。但这也是典型的时间换空间。

缺点:缺点不言而喻。步骤还比第一种还多了个整理的过程,时间效率,相对来说太低了。所以我们尽量去触发这种gc算法的垃圾回收器。

本文使用 文章同步助手 同步