JVM--垃圾回收算法

1.GC垃圾回收算法

1.1可达性分析算法

实现过程:
	1.可达性分析算法根据GC Root(根对象)作为起始点,按照从上到下的方式遍历确认GC Root->obj是否可达
	2.每一条路径称为一条引用链,如果目标对象与GC Root没有任何引用链相连,则标记为不可达
	3.在触发GC回收之前对象会自动调用内部的终止方法finalize(),该方法可以通过重写来复活该对象(只能调用一次)
	4.当检测到finalize()方法并未建立与GC Root的引用链,则会在第二次标记后清除该对象
优点:
	1.解决了引用计数器法中无法解决的循环引用的问题
	2.不需要每个对象都分配一个计数器
缺点:
	1.还是会产生内存碎片,当对象大量被回收后,内存碎片将可能会导致服务器的崩溃

算法具体过程如图所示:

  1. 从GC Root开始搜索,搜索过程中查询到Obj6和Obj7为不可达对象
    在这里插入图片描述
  2. 标记不可达对象如下图的obj6和obj7,判断这两个对象是否在finalizer链表中,我们假设obj6有复活对象的操作,obj7无复活对象操作,但是都有finalize方法的重写
    在这里插入图片描述
  3. 执行finalize方法后,复活的对象会重新生成一条引用链,而不能复活的对象则会直接被标记为可回收对象
    在这里插入图片描述
  4. 第二次GC触发后,就会直接清除掉obj7,因为finalize方法只能执行一次
    在这里插入图片描述

1.2引用计数器算法(已淘汰)

实现过程:
	1.每个对象含有一个count值(计数器),初始值为1(自身引用)。
	2.判断该对象是否被引用,引用则count值+1
	3.若该对象引用失效后,则count值-1
	4.直到count值=0则表示该对象无引用,为可回收对象,并进行清除
优点:
	1.实现简单
	2.垃圾对象便于识别
	3.判断效率高,回收几乎无延迟
缺点:
	1.每个对象都需要配备计数器,当对象过多时,增加了大量的存储空间开销
	2.每次引用都需要更新计数器,更新计数器则会伴随着加减操作,增加了运算时间的开销
	3.引用计数器无法实现循环引用,循环引用会造成OOM

算法具体过程如图所示:

  1. 为每个对象分配一个计数器count=1
    在这里插入图片描述

  2. 当对象A被对象B引用,对象A的计数器则会+1;对象C的自身引用断开,则对象C的计数器则会-1
    在这里插入图片描述

  3. 当检测到计数器count=0,则会触发垃圾回收,留下一块内存碎片
    在这里插入图片描述

1.3 复制算法

问题:可达性算法已经将垃圾对象回收了,为什么还需要复制算法?
原因:可达性算法虽然可以解决引用计数法中无法解决的循环引用的问题,但是仍然会产生内存碎片,复制算法就是为了解决内存碎片问题而产生的。
实现过程:
	1.当可达性分析算法执行完成后,复制算法首先会初始化堆,将Survival区一分为二,并命名为From和To
	2.从GC Root开始遍历有向图,对每一个存活的对象进行复制(一个一个的复制),复制完成后对象的地址就会发生变化
	3.然后就需要更新GC Root的引用地址
	4.当所有对象遍历并更新到To空间以后,就需要对From空间的对象进行清除
	5.清除后需要将From和To进行一次Swap(交换)
优点:
	1.无内存碎片
	2.吞吐量高,不需要遍历全堆,只需要处理存活对象
	3.内存分配属于顺序分配,速度较快,只需要移动空闲指针(free pointer)
缺点:
	1.堆利用率低,To区永远是一块用于准备下一次复制的空闲堆空间

算法实现步骤如下图所示:

  1. 可达性算法判断出Eden区的存活对象,并将垃圾收集后,复制算法开始将Survival区分为相等的两块Heap,并命名为From和To
    在这里插入图片描述

  2. 其实复制算法并没有确定哪个是Eden区,哪个是From区,而是根据GC Root遍历搜索,每遍历一个对象就将它复制到To区,年龄此刻=1,复制进入后会建立新的引用链,这里位置较小,没画出来。
    在这里插入图片描述

  3. 复制完成后,交换From和To的指向指针,如图所示:

  4. 当To区满了以后就会触发minor GC对该To区和Eden区进行一次垃圾回收,回收后触发复制算法,如下图,objc和obj1、obj2为垃圾,被回收了,复制算法复制的对象进入了To区,并将From和To进行交换。
    在这里插入图片描述
    5.幸存者区域的对象,直到年龄>=15以后就会直接丢进老年区

源码地址:https://github.com/kongwu-/gc_impl/tree/master/copying

1.4标记清除算法

实现过程:
	1.当老年区内存空间不足,触发Major GC,会将可回收对象先进行标记(一次性标记)
	2.标记对象就会直接被清除(一次性清除)
优点:
	1.实现过程简单,由于在新生代中可达性分析过程中已经调用了一次finalize方法,此处无"缓刑"过程,标记即为可回收对象,直接被清除
缺点:
	1.会产生内存碎片
	2.效率慢,需要遍历两次,才能真正把垃圾清除

在这里插入图片描述

1.5标记整理算法

标记整理算法是根据标记清除算法中产生内存碎片问题而产生的

实现过程:
	1.标记过程与标记清除算法一致(这个过程执行了标记和清除)
	2.将标记存活的对象进行连续的内存分配(开始复制)
	3.将存活对象分配完成以后,边界以外的对象全部清除(复制完成后将边界外对象清除)
优点:
	1.解决了标记清除算法中存在的内存碎片化问题
	2.相对复制算法提高了内存的利用率
缺点:
	1.整理过程增加了一次遍历过程,效率更低了
	2.整理过程需要一块可以连续存放所有对象的堆内存作为分配担保,但是并没有,因此不适用于对象过多的情况

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Carl·杰尼龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值