理解JVM工作机制(五)垃圾回收算法

垃圾回收算法
垃圾分代收集

部分收集(Partial GC):指目标不是完整收集整个Java堆的垃圾收集,其中又分为:

  • 新生代收集(Minor GC/Young GC): 指目标只是新生代的垃圾收集。
  • 老年代收集(Major GC/Old GC): 指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。

另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。

  • 混合收集(Mixed GC): 指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
  • 整堆收集(Full GC): 收集整个Java堆和方法区的垃圾收集。
标记-清除

在这里插入图片描述

在Java堆中标记需要清除的对象并执行清除

这是最基本的算法。 分两个步骤

  • 标记(Mark)过程:遍历所有的GC Roots,然后将所有GC Roots不可达的对象标记成不可存活的对象
  • 清除(Swep)过程:清除的过程将遍历堆中所有的对象,将标记的对象全部清除掉

标记清除的过程
在这里插入图片描述

标记-复制

为了解决效率问题,一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一一块。当这一块的内存用完了 ,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效
在这里插入图片描述

优点:避免内存碎片

缺点:对堆内存造成了浪费,可用内存缩小了一半

优化方案 (Apple式回收):

将内存分为三块: Eden、From Survivor、To Survivor,比例是 8:1:1,每次使用 Eden 和其中一块 Survivor。回收时,将 Eden 和 Survivor 中还存活的对象一次性复制到另外一块 Survivor 空间上,最后清理掉 Eden 和刚才使用的 Survivor 空间。这样只有 10% 的内存被浪费。

但是我们无法保证每次回收都只有不多于 10% 的对象存活,当 Survivor 空间不够,需要依赖其他内存(指老年代)进行分配担保。

分配担保

为对象分配内存空间时,如果 Eden+Survivor 中空闲区域无法装下该对象,会触发 MinorGC 进行垃圾收集。但如果 Minor GC 过后依然有超过 10% 的对象存活,这样存活的对象直接通过分配担保机制进入老年代,然后再将新对象存入 Eden 区。

标记-整理

标记:它的第一个阶段与标记/清除算法是一模一样的,均是遍历 GC Roots,然后将不可达的对象标记。

整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。因此,第二阶段才称为整理阶段。

在这里插入图片描述

这是一种老年代的垃圾收集算法。老年代的对象一般寿命比较长,因此每次垃圾回收会有大量对象存活,如果采用复制算法,每次需要移动大量存活的对象,效率很低。

分代收集算法

根据对象存活周期的不同,将内存划分为几块。一般是把 Java 堆分为新生代和老年代,针对各个年代的特点采用最适当的收集算法。

  • 新生代:复制算法
  • 老年代:标记-清除算法、标记-整理算法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值