zoukankan      html  css  js  c++  java
  • 第六章 JVM垃圾收集器(2)

    上一章记录了几种常见的垃圾收集器,见《第五章 JVM垃圾收集器(1)

    R大的建议:小于8G的都用CMS,大于8G的选择G1

    1、G1

    说明:

    • 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除),实际上G1回收器的整个堆内存的划分都与其他收集器不同。
    • CMS需要配合ParNew,G1可单独回收整个空间

    原理:

    • G1收集器将整个堆划分为多个大小相等的Region
    • G1跟踪各个region里面的垃圾堆积的价值(回收后所获得的空间大小以及回收所需时间长短的经验值),在后台维护一张优先列表,每次根据允许的收集时间,优先回收价值最大的region,这种思路:在指定的时间内,扫描部分最有价值的region(而不是扫描整个堆内存),并回收,做到尽可能的在有限的时间内获取尽可能高的收集效率。

    运作流程:

    • 初始标记:标记出所有与根节点直接关联引用对象。需要STW
    • 并发标记:遍历之前标记到的关联节点,继续向下标记所有存活节点。
      • 在此期间所有变化引用关系的对象,都会被记录在Remember Set Logs中
    • 最终标记:标记在并发标记期间,新产生的垃圾。需要STW
    • 筛选回收:根据用户指定的期望回收时间回收价值较大的对象(看"原理"第二条)。需要STW

    优点:

    • 停顿时间可以预测:我们指定时间,在指定时间内只回收部分价值最大的空间,而CMS需要扫描整个年老代,无法预测停顿时间
    • 无内存碎片:垃圾回收后会整合空间,CMS采用"标记-清理"算法,存在内存碎片
    • 筛选回收阶段:
      • 由于只回收部分region,所以STW时间我们可控,所以不需要与用户线程并发争抢CPU资源,而CMS并发清理需要占据一部分的CPU,会降低吞吐量。
      • 由于STW,所以不会产生"浮动垃圾"(即CMS在并发清理阶段产生的无法回收的垃圾)

    适用范围:

    • 追求STW短:若ParNew/CMS用的挺好,就用这个;若不符合,用G1
    • 追求吞吐量:用Parallel Scavenge/Parallel Old,而G1在吞吐量方面没有优势

    2、几点注意

    问题1、G1以外的其他收集器在回收垃圾的时候:要不只是扫描年轻代,要不只是扫描年老代。在年轻代的回收过程中,如果旧生代中的对象引用了年轻代的对象,那么我们只扫描年轻代就不行了,但是由于年老代一般而言是年轻代的3倍大小,如果年轻代、年老代一起去扫描的话,效率会急剧下降,这个问题怎么处理?

    :JVM采用remember set来做的这个事儿,当发现一个引用对象被赋值时,JVM发出一个write barrier指令来暂时中断写操作,检查被赋值的引用对象是不是处于年老代,且其引用的对象是不是处于新生代(即是不是年老代对象引用了年轻代对象),如果是,将相关引用信息记录到remember set。之后的扫描,我们会从根集合+remember set向下进行扫描。(也就是说真正的根集合,是JVM定义的根集合+remember set

    问题2、G1收集器为了做到GC时间可预测,采用扫描部分价值最大的region来实现,那么如果这部分region中的对象被其他region中的对象所引用,那么仅扫描前者可能就不行了,但是如果扫描全部region的话,又无法做到GC时间可预测,效率会大大下降,怎么办?

    :G1同理,为每一个region分配一个remember set,当发现一个引用对象被赋值时,JVM发出一个write barrier指令来暂时中断写操作,检查被赋值的引用对象与其引用的对象是不是处于不同的region(eg.a=b;检查a与b是不是在不同的region),如果是,将相关引用信息记录到当前region的remember set。之后的扫描,我们会从根集合+remember set向下进行扫描。

    问题3、CMS与G1在并发标记的时候若发部分引用对象的引用关系发生了变化,怎么处理才能让重新标记的时候仅仅扫描出这些变化?

    :在并发标记期间,对象的引用关系若发生了变化,这些相关的记录就会记录到remember set logs在重新标记阶段,将该logs的信息加入到remember set中去,然后再从remember set去向下trace节点。

  • 相关阅读:
    波段是金牢记六大诀窍
    zk kafka mariadb scala flink integration
    Oracle 体系结构详解
    图解 Database Buffer Cache 内部原理(二)
    SQL Server 字符集介绍及修改方法演示
    SQL Server 2012 备份与还原详解
    SQL Server 2012 查询数据库中所有表的名称和行数
    SQL Server 2012 查询数据库中表格主键信息
    SQL Server 2012 查询数据库中所有表的索引信息
    图解 Database Buffer Cache 内部原理(一)
  • 原文地址:https://www.cnblogs.com/java-zhao/p/5183999.html
Copyright © 2011-2022 走看看