Java内存回收机制GC(四)

垃圾收集算法

分代收集理论

定义:

​ JVM的垃圾收集都采用分代收集算法,就是将堆分为**新生代和老年代**,这样我们可以根据各个年代的特点选择 合适的垃圾回收算法

标记复制算法

定义:

​ 将内存分为大小相同的两块,每次只使用其中的一块,当进行垃圾回收时,将还存活的对象复制到另一块去,然后把使用的空间一次清理

缺点:

​ 每次只能使用一半的内存

优点:

​ 避免内存碎片的产生

标记复制算法

标记清除算法

定义:

​ 用GC Roots标记存活的对象,统一回收所有未被标记的对象

缺点:

  • 内存碎片产生 —— 标记清除后会产生大量不连续的碎片

  • 效率不高 —— 如果需要标记的对象太多,效率不高

标记清除算法

标记整理算法

定义:

​ 用GC Roots标记存活的对象将这些对象往一端移动,然后直接清除 端边界以外的内存

缺点:

  • 效率不高

标记整理算法

垃圾收集器

垃圾收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现

垃圾收集器配合使用图:

垃圾收集器配合使用图

Serial收集器

参数:

-XX:+UseSerialGC(年轻代), -XX:+UseSerialOldGC(老年代)

定义:

​ 一个单线程收集器,在GC过程中,必须暂停其他所有的工作线程( “Stop The World” ),直到GC结束

算法:

新生代采用复制算法,老年代采用标记-整理算法。

优点:

  • 简单高效 —— 因为没有上下文切换,获得很高的单线程效率

缺点:

  • STW影响用户体验

Serial收集器图

Parallel Scavenge收集器

参数:

-XX:+UseParallelGC(年轻代), -XX:+UseParallelOldGC(老年代)

-XX:ParallelGCThreads (指定收集线程数)

定义:

​ 就是Serial收集器的多线程版本,关注点是吞吐量(高效率的利用CPU)使得GC时间尽可能短

JDK8默认的新生代和老年代收集器

算法:

新生代采用复制算法,老年代采用标记-整理算法。

Parallel Scavenge收集器原理

CMS收集器

参数:

-XX:+UseConcMarkSweepGC(old)

定义:

​ 是一种 获取最短回收停顿时间为目标【STW的时间】 收集器, 实现了让垃圾收集线程与用户线程并行工作

算法:

​ 基于 “标记-清除”算法实现,用到 三色标记法的增量更新算法

优点:

  • 并发收集
  • 低停顿 —— STW时间比Parallel Scavenge长,但用户的感知短。

缺点:

  • 浮动垃圾 —— 并发标记和并发清理时产生的垃圾没办法处理
  • 内存碎片 —— -XX:+UseCMSCompactAtFullCollection参数设置做整理
  • concurrent mode failure —— 并发模式失败,会转为 serial old垃圾收集器来回收 【GC过程又有大对象移动到老年代
    • 通过参数-XX:CMSInitiatingOccupancyFraction调整当老年代使用达到某个值 [默认92%] 触发full GC,调小一点,避免大对象移动老年代导致==并发模式失败==

过程:

过程操作
初始标记Stop The World
记下GC Roots直接引用的对象【直接速度快!
并发标记从记下的直接引用对象开始遍历整个对象图
【不需要STW
有可能漏掉标记
重新标记并发标记里面==漏标的对象进行标记==
【短时间的STW
基于三色标记的增量更新算法
并发清理开启用户线程,GC对未标记区域清扫
此时有新增对象标记为黑色,不做处理
并发重置重置本次GC标记的数据【颜色

CMS收集器

优化

优化本质上就是让短期存活的对象尽量都留在survivor里,不要进入老年代,这样在minor gc的时候这些对象都会被回收,不会进到老年代从而导致full gc

三色标记算法

定义:

GC Roots可达性分析算法遇到的对象,标记为三种颜色:

  • 黑色本对象和引用都完全访问
  • 灰色本对象访问,但引用不全都访问
  • 白色本对象未被访问

漏标、多标问题

  1. 当CMS算法执行到这里,还没有来得及标记 D点

CMS会导致的问题图1

  1. 并发下,用户线程将A.d的引用指向B.d,B.d的引用置NULL

D

  1. 导致D未变色,作为垃圾对象【白色】被清除

在这里插入图片描述

解决问题

增量更新

定义:

​ 当黑色对象A插入新的指向白色对象D的引用关系时,会保存新插入的引用;等并发标记结束后,在重新标记阶段将这些黑色对象A作为根再次扫描 【重新标记会STW

​ 简化理解为, 黑色对象一旦新插入了指向白色对象的引用之后, 它就变回灰色对象了

原始快照

定义:

​ 当灰色对象B要删除指向白色对象D的引用关系时, 会保存要删除的引用, 在并发标记结束后, 在重新标记阶段将这些灰色对象B作为根再次扫描 【重新标记会STW

写屏障

定义:

写屏障类似于AOP操作,在插入之前或者删除之前变更的引用记录下来。

使用:

增量更新 和 原始快照都用到了写屏障

例子:

/* 实现SATB 快照 */
void pre_write_barrier(oop* field) {
    oop old_value = *field;    // 获取旧值
    remark_set.add(old_value); // 记录原来的引用对象
}


/* 实现增量更新 */
void post_write_barrier(oop* field, oop new_value) {  
    remark_set.add(new_value);  // 记录新引用的对象
}

应用

下面垃圾收集器,针对漏标的处理方案:

垃圾收集器方案
CMS写屏障 + 增量更新
G1写屏障 + SATB
Shenandoah写屏障 + SATB
ZGC读屏障
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值