厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>

前言

在看狂神频道的时候偶然发现下图,感触颇深。特别在当今【程序 = 业务 + 框架】思想盛行的开发者中,夯实基础基础显得格外重要,因此开此专栏总结记录。
厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第1张图片

对于对于JVM的学习,由于在工作中的业务场景几乎使用不到,所以总是学了忘忘了学,争取早日理解哈哈,学习博客:

  1. 厚积薄发打卡Day62 :【狂神】狂神JVM快速入门(上)<从JVM体系到native方法>
  2. 厚积薄发打卡Day63 :【bugstack & 狂神】狂神JVM快速入门(中)<从‘程序计数器’到‘Dump内存快照’>
  3. 厚积薄发打卡Day64 :【狂神 & bugstack】狂神JVM快速入门(下)<GC机制与算法>

常用GC算法介绍

分代回收:

前面提到过Java的堆内存被分代管理,那为什么要分代管理呢?分代管理主要是为了方便垃圾回收。

这样做是基于两个事实:

  1. 第一是大部分对象很快就不再使用了
  2. 第二是还有一部分不会立即无用,但也不会持续很长时间

因此,虚拟机中划分为年轻代、老年代和永久代,我们来看图:

厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第2张图片

  • 年轻代:

    • 主要用来存放新创建的对象
    • 年轻代分为eden 区和两个survival 区,大部分对象在Eden 中生成
    • 当Eden区满时,对象会在两个survival 区交替保存,达到一定次数后,对象会晋升到老年代
  • 老年代:

    • 用来存放从年轻代晋升而来的存活时间较长的对象
  • 永久代前面也介绍过主要保存类信息等内容

    • 这里的永久代是指对象划分方式,不是专指1.7的Permanent Generation 或者1.8 之后的meta space
  • 根据年轻代与老年代的特点:

    • JVM提供了不同的垃圾回收算法:
    • 垃圾回收算法按类型可以分为:
      • 引用计数法
        • 引用计数法是通过对象被引用的次数来确定对象是否还在被使用
        • 缺点是无法解决循环引用的问题
      • 复制法标记
        • 复制算法需要from 和to 两块儿大小相同的内存空间,对象分配时只在form 块中进行
          回收时把存活对象复制到 to 块中,并清空from 块,然后交换两块的分工
        • 把from 块儿作为to块,把to 块儿作为from 块
        • 缺点是内存使用率较低
      • 标记清楚算法:
        • 标记清除算法分为标记对象和清除不再使用的对象两个阶段
        • 标记清除算法的缺点,是会产生内存碎片
  • JVM中垃圾回收器

    • 新生代:
      1. Serial
        • 算法:标记-复制算法
        • 说明:简单高效的单核机器,Client 模式下默认新生代收集器;
      2. Parallel ParNew
        • 算法: 标记-复制算法
        • 说明:GC 线程并行版本,在单 CPU 场景效果不突出。常用于 Client 模式 下的 JVM
      3. Parallel Scavenge
        • 算法:标记-复制算法
        • 说明:目标在于达到可控吞吐量(吞吐量=用户代码运行时间/(用户代码运 行时间+垃圾回收时间))
    • 老年代
      1. Serial Old
        • 算法:标记-压缩算法
        • 说明:性能一般,单线程版本。1.5 之前与 Parallel Scavenge 配合使用;作 为 CMS 的后备预案。
      2. Parallel Old
        • 算法:标记-压缩算法
        • 说明:GC 多线程并行,为了替代 Serial Old 与 Parallel Scavenge 配合使 用。
      3. CMS
        1. 算法:标记-清除算法
        2. 说明:对 CPU 资源敏感、停顿时间长。标记-清除算法,会产生内存碎 片,可以通过参数开启碎片的合并整理。基本已被 G1 取代
    • G1
      • 算法:标记-压缩算法
      • 说明:适用于多核大内存机器、GC 多线程并行执行,低停顿、高回收效率。

垃圾回收算法:

下面我们详细介绍几个典型的垃圾回收算法

cms 回收算法

厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第3张图片

  • CMS 是JDK1.7以前可以说最主流的垃圾回收算法
    • CMS 使用标记清除算法你,优点是并发收集停顿,我们看图中CMS 的处理过程:
      1. CMS 的第一个阶段是初始标记,这个阶段会stop the word 标记的对象只是从root,最直接可达的对象
      2. 第二个阶段是并发标记,这时GC 线程和应用线程并发执行主要是标记可达的对象
      3. 第三个阶段是重新标记阶段,这个阶段是第二个stop the world 阶段,停顿时间比并发标记要小很多,但比初始标记稍长,主要对对象进行重新扫描并标记
      4. 第四个阶段是并发清理阶段进行并发的垃圾清理,最后一个阶段是并发重置阶段,为下一次GC重置相关数据结构

G1算法:

  • 这一算法在jdk1.9 后成为了JVM的默认垃圾回收算法
  • G1的特点是保持高回收率的同时将,减少停顿记忆算法,取消了追踪年轻代与老年代的物理划分,但它仍然属于分代收集器,这一算法将对于分为若干个区域,称为region
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOTEJ5Mb-1627385873502)(厚积薄发打卡Day76 :【MSUP】深入浅出JVM(下)常用GC算法及考察点/厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第4张图片
    )]
  • 如图中的小方格所示:
    • 一部分区域用作年轻代
    • 一部分用作老年代
    • 还有另外一种专门用来存储巨型对象的分区
  • G1和CMS 一样会遍历全部对象,然后标记对象一种情况,在清除对象后会对区域进行复制,移动整合碎片空间
    • 图的右边是这一年轻代与老年代的回收过程:
      • G1的年轻代回收采用复制算法并行进行收集,收集过程会stop the world,这一个老年代回收
      • 同时也会对年轻代进行回收,主要分为四个阶段:
        • 第一个阶段依然是初始标记阶段,完成对根对象的标记这个过程,这时会 stop the word
        • 第二个阶段并发标记阶段,这个阶段是和用户线程并行执行的
        • 第三个阶段最终标记阶段,完成三色标记的标记周期
        • 第四阶段复制/清除阶段,这个阶段会优先对可回收空间较大的region进行回收,即garbage first(G1),这也是记忆名称的由来
    • 这一采用每次只清理一部分,而不是全部religion 的增量式清理,由此来保证每次gc停顿时间不会过长
  • 总结一下这一算法,这部分需要掌握
    • 这一是逻辑分代,不是物理分代
    • 需要知道回收的过程和停顿的阶段
    • 此外还需要知道G1算法,允许通过JVM参数设置region 的大小范围是1~32M(兆)
    • 还可以设置期望的最大这些停顿时间等等
    • 如果你有兴趣:也可以对gms 和g1使用的三色标记算法,进行简单的了解

ZGC算法:

  • ZGC是最新的JDK1.11中提供的高效垃圾回收算法,ZGC针对大堆内存设计,可以支持tb级别的堆:
    • 它非常高效,能够做到十毫秒以下的回收停顿时间
  • 这么短的停顿时间,ZGC是如何做到的呢?

厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第5张图片

  • 我们来了解一下ZGC的黑科技:

    • ZGC使用了着色指针技术,
      • 我们知道,64位平台上一个指针可用位是64位,ZGC限制最大支持4tb的堆,这样寻址只需要使用42位,那么会剩下22位就可以用来保证额外的信息
      • 着色指针技术:就是利用指针的额外信息位在指针上对对象进行着色标记
    • 第二个特点是使用读屏障:
      • ZGC使用读屏障来解决GC线程和应用线程可能并发修改对象状态的问题,而不是简单粗暴的通过stop the world 来做全局的锁定,使用读屏障只会在单个对象的处理上有概率被减速
    • 第三个特点是ZGC的并发处理:
      • 由于读屏障的使用,进行垃圾回收的大部分时候都是不需要stop the world,因此ZGC的大部分时间都是并发处理
    • 第四个特点是基于region
      • 这与G1算法一样,不过虽然也分了region,但是并没有进行分代
      • ZGC的region不像G1那样是固定大小,而是动态决定region 的大小,region 可以动态创建和销毁,这样可以更好地对大对象进行分配管理
    • 第五个特点是压缩整理CMS 算法
      • 清理对象时原地回收,会存在内存碎片问题
      • ZGC 和G1一样,也会在回收后对region 中的对象进行移动合并,解决了碎片问题
  • 虽然ZGC的大部分时间是并发进行,但还是会有短暂的停顿,来看一下ZGC的回收过程,这张图是按ZGC的回收时序绘制的:

    厚积薄发打卡Day77 :【MSUP】深入浅出JVM(下)<常用GC算法及考察点>_第6张图片

    • 我们从上往下看,初始状态是整个堆空间被划分为大小不等的许多region,即图中绿色的方块
    • 开始进行回收时,ZGC首先会进行一个短暂的stop the world,来进行如此根对象的标记
      • 这个步骤非常短,因为如此的总数量通常比较小,然后就开始进行并发标记
    • 如图,通过对对象指针进行着色来进行标记,结合读屏障解决单个对象的并发问题,其实这个阶段在最后的时候还会有一个非常短的stop the world
      停顿用来处理一些边缘情况
      • 这个阶段绝大部分时间都是并发进行的,所以没有明显标示出这个停顿
    • 下一个阶段是清理阶段
      • 这个阶段会把标记为不可用的对象进行回收,如图,把橘色的不再使用的对象进行了回收
    • 最后一个阶段是重定位,
      • 重定位就是对这些后存活的对象进行移动,来腾出大块的内存空间解决碎片问题,在重定位最开始会有一个短暂的stop the world,用来重定义集合中的root 对象,暂停时间取决于入头的数量和重定位及与对象的总活动级的比率
    • 最后是并发重定位,这个过程也是通过读屏障与应用线程并发进行的

考察点和加分项:

总结一下JVM 相关的面试考察点:

  1. 需要理解JVM 的内存模型和java 的内存模型
  2. 要了解类的加载过程,了解双亲委派机制
  3. 要理解内存的可见性与java 内存模型对原子性可见性,有序性的保证机制
  4. 要了解常用的这些算法的特点,执行过程和适用场景
    1. 例如G1适合对最大延迟有要求的场合,ZGC适用于六十四位系统的大内存服务中
  5. 要了解常用的JVM参数,明白对不同参数的调整,会有怎样的影响,适用于什么样的场景:
    1. 比如垃圾回收的并发数
    2. 偏向锁的设置等

你可能感兴趣的:(MSUP,面试题,JVM学习,算法,jvm,java)