深入理解JVM--G1垃圾收集器

深入理解JVM--G1垃圾收集器

  1. 吞吐量:
    1. 吞吐量关注的是,在一定时间内,最大化一个应用的工作量
    2. 用一段时间内同一个事务(或者任务,请求)完成的次数(tps)来衡量系统吞吐量的好坏
    3. 对于关注吞吐量的系统,卡顿是可以接受的,因为这个系统关注的是长时间大量任务的执行能力,单次快速的响应不值得考虑
  2. 响应能力:
    1. 响应能力指的是一个程序或系统对一个请求能否及时响应,比如:
      1. 一个桌面UI是否能快速响应一个事件
      2. 一个网站能多快返回一个系统请求
      3. 数据库能多快查找目标数据
    2. 对于这类对响应时间敏感的产品,长时间停顿是无法接受的
  3. G1收集器设计目标:
    1. 能与应用线程一起工作,几乎不需要STW(Stop The World)
    2. 整理剩余空间,不需要产生内存碎片(CMS只有在Full GC时,用STW整理内存碎片)
    3. GC停顿更加可控
    4. GC不需要额外的内存空间(CMS需要分配额外的内存空间处理浮动垃圾)
    5. 更大的吞吐量和更小的响应时间
    6. G1的设计计划是替换掉CMS
      1. G1在某些方面比CMS更有优势,比如CMS采用标记-清除算法(Mark-Sweep),会产生大量的内存碎片,而G1收集器采用复制算法,不会产生这个问题
      2. G1提供了更多的手段,使得GC停顿时间更加可控
      3. Eden、Survivor、Old区不再固定,在内存使用效率上更灵活
      4. G1在回收内存后买上做合并空闲内存的操作,而CMS默认是在STW的时候做
      5. G1可以在新生代和老年代使用,而CMS只能在老年代使用
  4. G1收集器重要概念:
    1. G1收集器是一个面向服务端的垃圾收集器,适用于多核处理器,大内存的服务端系统
    2. 它满足短时间GC停顿的同时还能达到较高的吞吐量
    3. JDK7以上版本适用
    4. 分区(Region)
      1. G1采用了不同的策略来解决并行、串行、内存碎片、GC停顿时间等问题——G1将整个堆分成相同大小的分区,每个分区都有一个分代的角色:Eden、Survivor、Old
      2. G1对每个角色的数量没有做强制限定,每种分代的内存大小,可以动态分配
      3. G1从多个Region中复制存活的对象,然后集中放入一个Region中,同时整理,清除内存(复制算法)
      4. 每个分区既可以是新生代也可以是老年代,但是同一时间只能属于某个代,年轻代、幸存区、老年代这些概念都还存在,成为逻辑上的概念,这样方便复用之前分代框架的逻辑
      5. G1依然是在新生代满了之后,对新生代进行回收,至于新生代也采取分区机制的原因,则是因为这样与老年代策略统一,方便调整代的大小
      6. 除了Eden、Survivor、Old区,G1中还有一块特殊的区域,叫Humongous
        1. 如果一个对象占用空间达到或超过了分区的50%,G1就会认为该对象是巨型对象,这些巨型对象会默认分配到老年代
        2. 但是如果这是一个短期存在的巨型对象,就会对垃圾收集器产生负面影响,所以G1专门划分了一个Humongous区,来存放这些巨型对象,如果一个H区装不下该对象,则G1会寻找连续的H区来存储,因此 有时候会因为找不到而不得不进行Full GC
      7. G1使用了停顿时间可预测模型,来满足用户设定的GC停顿时间,根据用户设定的停顿时间,GC自动选择哪些Region要清除,一次清除多少个Region
      8. 由于物理内存上不需要连续,导致有的分区垃圾对象较多,有些分区较少,G1会优先回收垃圾对象较多的区域,这也就是G1名字的由来,即首先收集垃圾较多的区域
      9. 使用G1时堆内存分配的大概示意图:
        在这里插入图片描述
  5. G1还是一种带压缩的收集器,即将一个存活的对象从一个分区拷贝到另一个分区时,这个过程是一个局部压缩的过程
  6. 收集集合(CSet): 一组可被回收的分区的集合(告诉垃圾收集器哪些分区中有大量垃圾可以进行垃圾回收),从CSet中存活的数据会在GC过程中移动到另一个可用分区,CSet中的分区可以来自Eden、Survivor、Old
  7. 已记忆集合(RSet)
    1. RSet记录了Region中的对象引用本Region中对象的关系(如在A分区中的对象a引用了B分区中的对象b,则在B分区中的RSet会有一条记录,记录了该引用),属于points-into结构(谁引用了我的对象),RSet的价值在于使得垃圾收集器不需要扫描整个堆找到谁引用了当前分区中的对象,只需要扫描RSet即可
    2. RSet并不会记录新生代对象之间的引用,原因是每次进行GC都会对所有新生代对象进行扫描,所以RSet只需要记录老年代到新生代的引用即可!
    3. 这个RSet其实是一个HashTable,key是别的Region的起始地址,value是一个集合,里面的元素是card table的index。举例来说,如果Region A的RSet里有一项key是Region B,value里有index为1234的card,它的意思就是Region B的一个card中有引用指向Region A。所以对于Region A来说,该RSet记录了points-into的关系;而card-table仍然记录了points-into的关系(看不懂,以后可能会懂?/(ㄒoㄒ)/~~)
  8. G1的两种GC模式
    1. Young GC(STW)
      1. Eden区满了后进行,选用所有年轻代里的Region,通过控制年轻代Region个数,即年轻代内存大小,来控制Young GC内存开销,进行完Young GC后,所有年轻代的Region都会被回收
      2. Young GC步骤:
        1. 根扫描:静态和本地对象被扫描
        2. 更新RSet:处理dirty card更新RSet
        3. 处理RSet:检测年轻代中指向老年代的对象
        4. 对象拷贝:将年轻代代中存活的对象拷贝到Survivor/Old区中
        5. 处理引用队列
    2. Mixed GC(STW)
      1. 选定所有年轻代里的Region,外加根据global concurrent marking统计得出收益最高的若干老年代Region。在用户指定的开销目标范围内尽量选择收益较高的老年代Region
      2. Mixed GC不是Full GC,它只能回收部分老年代的Region,如果Mixed GC的速度无法跟上程序分配内存的速度,就会使用Serial Old(Full GC)来收集整个GC heap,所以本质上,Mixed GC不是Full GC
      3. global concurrent marking:执行过程类似CMS,但在G1 GC中,只为Mixed GC提供标记作用,不是GC过程中必要环节,具体步骤如下:
        1. 初始标记(Initial Mark):标记了从GC Root可以直接到达的对象,因为共用Young GC的暂停,所以可以说global concurrent marking伴随Young GC发生
        2. 并发标记(Concurrent Mark):并发,从GC Roots开始对Heap中的对象进行标记,收集各个Region中对象存活信息
        3. 重新标记(Remark):STW,标记那些在并发过程中发生改变的对象
        4. 清理(Clean):清除空Region(里面没有任何存活对象的Region),加入到Free list,不需要STW
      4. G1会在Young GC和Mixed GC间不断切换运行,同时定期做并发标记,在实在赶不上对象创建速度的情况下会执行Full GC(Serial Old)
  9. 三色标记算法
    1. 提到并发标记,我们就不得不的了解并发标记的三色标记算法。它是描述追踪器和回收器的一种有效方法,利用它可以推演回收的正确性
    2. 三色标记算法将对象分为三种类型
      1. 黑色:根对象,或者该对象与它的子对象都被扫描过(对象被标记了,且它所有的Field都被扫描过了)
      2. 灰色:对象本身被扫描过了,但是还没有扫描过它的子对象
      3. 白色:未被扫描的对象,扫描完所有对象后,最终被标记为白色的对象为不可达对象,即垃圾对象
    3. 三色标记算法图示
      在这里插入图片描述
    4. 三色标记算法的对象丢失问题
      在这里插入图片描述
  10. STAB(解决三色算法问题)
    1. 在开始标记时生成一个快照图,标记存活对象
    2. 在并发标记时将所有改变的对象入队(在write barrier里将所有旧的引用所指向的对象变为非白的)
    3. 在三色算法并发标记的阶段,对于从gray对象移除的目标引用对象标记为gray,对于black引用的新产生的对象标记为black
    4. 在GC收集的时候,所有新生代的对象都被认为是活的除此以外不可到达的对象都认为是垃圾对象
    5. 可能存在浮动垃圾,下次GC回收
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值