06-底层必备源码-JVM底层-GC算法流程(自我总结)

2023-11-06

一 判断 是否GC 的算法

1.引用计数法:

1.1 规则:如果这个obj被引用,计数器+1,引用失效,计数器-1。当一个obj的引用计数器为0,就不代表被使用。

1.2 缺点:不能解决循环引用的问题

2.可达性分析算法

2.1 规则:以GCroot为起点,向下搜索,经过的链为引用链,当一个obj没有任意一个到GCroot的引用链,证明他可以被回收。

2.2 可作为GCroot的对象:

  • java虚拟栈的引用对象
  • 方法区的静态属性、常量引用的对象
  • 本地方法区中引用的对象

二 GC 的具体算法

1.标记-清除:首先标记出需要回收的对象,标记完成之后统一清除对象。

标记:从根集合开始扫描,标记存货的对象

清除:扫描整个堆内存空间,回收未被标记的对象,使用free-list记录可以使用的区域

优点:基于最基础的可达性分析算法,它是最基础的收集算法;而后续的收集算法都是基于这种思路并对其不足进行改进得到的;

缺点:

  • 效率问题:标记和清除都需要扫描,两个过程的效率都不高;
  • 空间问题:标记清除后会产生大量不连续的内存碎片,这会导致分配大内存对象时,无法找到足够的连续内存,从而需要提前触发另一次垃圾收集动作。
  • stop-the-Word:在标记时需要暂停JVM用户进程

2.标记-复制:它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完之后,就将还存活的对象复制到另外一块上面,然后在把已使用过的内存空间一次理掉。

JVM实现原理:Survivor区,一块叫From,一块叫To,对象存在Eden和From块。当进行GC时,Eden存活的对象全移到To块,而From中,存活的对象按年龄值确定去向,当达到一定值(年龄阈值,通过-XX:MaxTenuringThreshold可设置,默认=15)的对象会移到年老代中,没有达到值的复制到To区,然后直接清空Eden和From。之后,From和To交换角色,新的From即为原来的To块,新的To块即为原来的From块,且新的Form块中对象年龄加1.

优点:内存分配时也不用考虑内存碎片等问题;实现简单,运行高效;可以利用指针碰撞(bump-the-pointer)实现快速内存分配

缺点:

  • 空间浪费:可用内存缩减为原来的一半,太过浪费(解决:可以改良,不按1:1比例划分);
  • 效率随对象存活率升高而变低:当对象存活率较高时,需要进行较多复制操作(对象的引用地址需要复制),效率将会变低,所以该算法不适合对象存活率较高的场景或者区域。

应用场景:

  • 现在商业JVM都采用这种算法(通过改良缺点1)来回收新生代;
  • 如Serial收集器、ParNew收集器、Parallel Scavenge收集器、G1(从局部看)。

3. 标记-整理 算法

标记-整理:标记操作和“标记-清理”算法一致,后续操作不只是直接清理对象,而是在清理无用对象前,先将存活的对象都向一端移动,并更新引用其对象的指针,然后直接清理掉端边界以外的内存。

标记:和“标记-清理”算法一致

整理:扫描整个堆内存空间,将存活的对象都向一端移动,并更新引用其对象的指针,然后直接清理掉边界以外的内存。

整理的目的 :就是整合零散分布的空间碎片为一个连续的空间。

优点:

  • 不会像复制算法,效率随对象存活率升高而变低
  • 不会像标记-清除算法,产生内存碎片,因为清除前,进行了整理,存活对象都集中到空间一侧;

缺点:主要是效率问题:除像标记-清除算法的标记过程外,还多了需要整理的过程,效率更低;

应用场景:回收老年代;

4、标记-清除-整理(Mark-Sweep-Compact)

该算法是标记清除和标记整理的结合,

标记-清除会产生碎片,

标记-整理每次都进行整理效率不高;

标记-清楚-整理 是如果老年代内存中没有一块连续续的空间可以存放将要进入对象,就进行整理;

如果内存中的空间可以存放将要进入的对象,就进行标记-清除,这样就节省了整理的步骤可以提高效率。总结一句话:不是所有的时候都需要整理的,因为整理也付出代价。主要应用于老年代。

总结: 没有最好的算法,只有最合适的引用场景

三 新生代、老年代对象存放原则

  • 1. 对象优先在eden区分配
  • 2.大对象直接放入老年代
  • 新生代GC回收算法采用的是复制算法;
    考虑到大对象可能的存活时间长,频繁复制带来额外开销;
    jvm通过设置参数值,当大于该值的对象直接放入老年代。
    123

  • 3.survivor区长期存活的对象移动到老年代
  • 新生代工作流程:
    1.对象放入eden区,直至eden区放不下该对象,发生youngGC
    2.Young GC流程是将Eden中有效的对象和survivor from区拷贝到 survivor to区
    3.清除eden区数据,将from和to指针交换
    ------
    survivor from中的部分数据存活时间可能过长,频繁复制带来额外开销,
    jvm通过利用age(每young gc交换一次 +1,默认15次)来判断是否将该对象移动到老年代,
    当对象的age==15时,将其移动到老年代
    12345678

  • 4.survivor区动态规划
  • 当survivor区发现有超过一半的对象age相同
    jvm会把这些对象移动到老年代
    12

  • 5.老年代担保原则
  • 当发生youngGC之前,jvm会检查老年代剩余空间是否大于当前新生代所有数据
    如果大于 直接顺利进行GC
    如果不大于,则判定这是一次不安全的GC,通过检查设置是否运行不安全GC,
    如果允许,则判断剩余空间是否大于历届youngGC平均值,如果是,直接进行youngGC
    如果不是,则对老年代进行full GC后,再进行YoungGC
    -----
    ps: 因为full GC的标记-整理算法耗时是youngGC的复制算法10倍以上
    
    12345678

    补充

  • YoungGC 又叫 MinorGC
  • 有种说法是对新生代进行垃圾回收叫做minor GC,对老年代进行垃圾回收叫做major GC,同时对新生代、老年代和永久代进行垃圾回收叫做full GC
  • 事实上有种说法是对新生代进行垃圾回收叫做minor GC,对老年代进行垃圾回收叫做major GC这个是对的,最后一句话存疑,我所参考的深入理解java虚拟机,对full GC的表述和majorGC相同,因为再进行MajorGC后必会发生一次YoungGC
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

06-底层必备源码-JVM底层-GC算法流程(自我总结) 的相关文章

随机推荐

  • EasyPoi 导出表格并设置表头

    EasyPoi 导出表格 EasyPoiUtil 工具类 设置表头 NewExcelExportStylerDefaultImpl 工具类 VO实体类 对应的是表的列名 Controller 1 未设置表头版本 Controller 2 设
  • hp服务器能不能装win7系统,惠普 HPC0Q07PA可不可以装windows7系统_惠普 HPC0Q07PA怎么安装win7系统-win7之家...

    刚买了一台惠普 HPC0Q07PA笔记本电脑 想安装windows7系统 但不知道能不能安装 也不知道装完win7系统之后系统运行的流畅不流畅 小编特意查了下惠普 HPC0Q07PA笔记本的相关信息 跟大家分析下这个能不能安装win7系统
  • 点云的关键点检测-传统方法总结

    三维点云的关键点检测可以通过以下步骤实现 1 寻找局部区域 从点云中选择一个局部区域 2 估计曲率和法线 对局部区域进行曲率估计 并计算法向量 3 计算关键点 使用曲率和法线信息来计算点云的关键点 这可以通过计算曲率极值点 曲率变化最大点或
  • Vue里使用Element UI的Tabs時el-tab-pane的隱藏和顯示

    1 效果圖 隱藏相關項后
  • tensorflow与tflearn的安装时numpy无法更新问题

    对于老司机来说 这都不是事 但对于初学者来说 在安装看到python里import tflearn 在安装tensorflow还真遇到了问题 电脑 mac python版本2 7 直接运行 sudo pip install tensorfl
  • Linux系统中如何查看TCP连接数

    这篇文章主要为大家展示了 Linux系统中如何查看TCP连接数 内容简而易懂 条理清晰 希望能够帮助大家解决疑惑 下面让小编带领大家一起研究并学习一下 Linux系统中如何查看TCP连接数 这篇文章吧 一 查看哪些IP连接本机 netsta
  • raid配置ssd为缓存_群晖SSD缓存有什么用?

    作用 SSD 缓存功能 使用户可以通过添加 SSD 提高 Synology NAS 上的随机访问性能 功能模式 只读缓存 使用此类型的 SSD 缓存时 只会将经常访问的数据存储在 SSD 缓存中以提高随机读取速度 因为 SSD 不涉及任何数
  • stm32 IAP APP 相互跳转实验 (keil4 jlink STM32F407ZE)

    1 实验目标 STM32 IAP学习时 希望有一个快捷的方式去实验IAP与APP之间的相互跳转 1 验证IAP跳转至APP 2 验证APP通过软件reset跳转至IAP 避免再一开始就实验完整的IAP过程 编写BootLoader 编写 A
  • flutter 高德地图 amap_flutter_location 隐私合规校验失败

    flutter 高德地图 amap flutter location 隐私合规校验失败 提醒 ios版本他的最新库是没有办法使用的 如果你的项目需要使用到iOS版本 请使用下面的路径 https github com yangsiyi41
  • 微信开发(js-sdk)中遇见的各种问题

    微信开发的准备工作 不熟 不是我来搞的 copy一下别人和官方的 1 绑定域名 先登录微信公众平台进入 公众号设置 的 功能设置 里填写 JS接口安全域名 备注 登录后可在 开发者中心 查看对应的接口权限 2 引入js文件 在需要调用JS接
  • 动态路由协议RIP配置实战

    1 RIP简介 RIP是一种基于距离矢量 Distance Vector 算法的协议 它使用跳数 Hop Count 作为度量值来衡量到达目的地址的距离 在RIP网络中 RIP协议要求网络中每一台路由器都要维护从自身到每一个目的网络的路由信
  • Kettle-动态数据链接,使JOB得以复用

    动态数据连接 使JOB得以复用 背景 移动执法系统在目前的主要的部署策略为1 N的方式 即总队部署一套 地市各部署一套 且基本都在环保专网 各地市的业务数据需要推送到总队系统 以便总队系统做整体的监督 决策 在整个数据对接过程中 基于Ket
  • Matlab导入txt文件

    有三种常见的方式 1 A importdata filename txt 则A就是n m的矩阵了 2 load filename txt 这样也是载入n m的矩阵 3 在MATLAB的work文件夹下 选择想要导入的数据 用右键import
  • 前端系列-1 HTML+JS+CSS基础

    背景 前端系列会收集碎片化的前端知识点 作为自己工作和学习时的字典 欢迎读者收藏和使用 笔者是后端开发 前端涉猎不深 因此文章重在广度和实用 对原理和性能不会过多深究 1 html 1 1 html5网页结构
  • 如何判断两条线段是否相交

    本篇是在 C 笔记 如何判断2个线段相交 的基础上加上自己的理解和实践总结出的判断两线段是否相交的方法 判断两条线段是否相交 先附上判断函数 bool judge int Ax1 int Ay1 int Ax2 int Ay2 int Bx
  • vue3的ref,unref,reactive,toRefs,toRef

    ref函数 接受一个初始值并返回一个响应式且可变的 ref 对象 ref 对象仅有一个 value属性 指向该初始值 const count ref 0 console log count value 0 count value conso
  • 判断图连通性的三种方法

    在看哥尼斯堡七桥问题的时候 谈到欧拉回路的问题 不免又想到了图的连通性 想到以后说不定会遇到相关问题 就做下连通性判断算法总结实现 如果一个图是连通的 那么从一个节点开始访问 采用深度优先或者广度优先对它进行遍历 那么必定能够访问完所有的节
  • xml转JavaBean

    在进行webservice通信的时候 需要解析xml为一个对象 由于个人也是第一次接触xml转对象 于是参考网上的例子写了一个工具类 所有jar包支持 fastjson dom4j public class XmlConverBeanUti
  • 数字化转型:科技赋能供给创造需求 附下载

    疫情对各行业及科创的影响我们都深切地感受到了 像AI家居 AR游戏等比较火爆的项目都是在疫情中喷发 此报告结合疫情驱动新兴技术演变及商业落地的态势 探讨数字化对于科创的意义 报告亮点 5G商业化将伴随成熟应用由点向面展开 人工智能和企业数字
  • 06-底层必备源码-JVM底层-GC算法流程(自我总结)

    一 判断 是否GC 的算法 1 引用计数法 1 1 规则 如果这个obj被引用 计数器 1 引用失效 计数器 1 当一个obj的引用计数器为0 就不代表被使用 1 2 缺点 不能解决循环引用的问题 2 可达性分析算法 2 1 规则 以GCr