美文网首页
jvm 优化篇-(8)-跨代引用问题(RememberSet、C

jvm 优化篇-(8)-跨代引用问题(RememberSet、C

作者: tianlang136520 | 来源:发表于2020-07-10 00:00 被阅读0次
死神-露琪亚

1、什么是跨代引用?

红色的线表示由虚拟机栈中发出的引用。显然B--->A、E--->F都是跨代引用。


跨代引用逻辑图

2、跨代引用对MonitorGC的影响

JVM GC 判断对象是否可以回收使用可达性分析的方法,可达性分析首先需要找到 GC Roots 对象。

常规GC-Root:

  • 1)虚拟机栈(栈帧中的局部变量表)中引用的对象【Stack Local】。
  • 2)本地方法栈(native方法)引用的对象。
  • 3)方法区中类静态属性、静态方法引用的对象。
  • 4)方法区中常量引用的对象。

MonitorGC个性GC-Root:

  • 5) RememberSet数据结构(CardTable是具体实现类似数组)

这里重点讲一下CardTable:
        作用:采用空间换时间,不需要扫描整个Heap空间,降低MonitorGC耗时。跨代引用带来的问题,采用CardTable很好的规避了遍历整个老年代的问题。
        HotSpot JVM的卡页(Card Page)大小为512字节,卡表(Card Table)被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。

CardTable标记着是否存在老年代引用新生代

如上图发现:B、C所在的Card Page在CardTable中被标记上了。

【思考🤔】MonitorGC的GC-Root中包括CardTable,如何提高MonitorGC效率?
就需要降低跨代引用的对象,尽量设置稍大些的From、To区域,尽量将对象消灭在Young Gen区域。同时也表示对象不是越早进入老年代越好(老年代对象引用新生代对象就是一个很好的说明)!!!。

3、跨代引用对CMS中 OldGC的影响

CMS-OldGC回收♻️分为7个步骤:


CMS的7个步骤
重点步骤解读:
  • 1、初始标记(Initial Mark)

    • 目标:标记出老年代中所有存活的对象。
    • 标记范围:Young Gen + Old Gen
    • 线程:JDK1.7是单线程,JDK1.8是多线程(-XX:+CMSParallelInitialMarkEnabled调整)
    • STW:触发Stop-The-World
    • 特点:速度极快
  • 2、并发标记(Concurrent Mark)

    • 目标:遍历阶段1初始标记出来的存活对象,然后继续递归标记这些对象可达的对象。(黑白灰三色标记法)。
    • 标记范围:Young Gen + Old Gen
    • STW:不触发
    • 特点:慢,很耗时。
    • 特殊操作:通过Old区卡片标记(Card Marking),提前把老年代空间逻辑划分为相等大小的区域(Card Page),如果引用关系发生改变,JVM会将发生改变的区域标记位“脏区”(Dirty Card)。JVM会对“并发标记”阶段应用线程新产生的对象及对象涉及的引用修改做记录(Mod-Union Table)
  • 3、预清理(Preclean)

    • 目标:2阶段中记录在Mod-Union Table的这些脏区会被找出来,刷新引用关系,清除“脏区”标记。
    • 标记范围: Old Gen。
    • 线程:GC线程和应用线程也是并发执行
    • STW:不触发
    • 特点:速度一般
  • 4、可中断的预清理(Concurrent Abortable Preclean)

    • 目标:降低垃圾回收时对应用的暂停时间,整个过程最耗时步骤在5(最终标记),所以4步骤提前进行。
    • 标记范围:Young Gen + Old Gen
      • 处理From、To区对象,标记可达到老年代的对象。
      • 和3阶段一样,扫描处理Dirty Card中的对象。
    • 线程:GC线程和应用线程也是并发执行
    • STW:不触发
    • 特点:速度一般
    • 特殊:下一个阶段要执行最耗时且STW的Remark阶段,Remark阶段会将整个YoungGen作为GC-Root进行操作,如果4阶段能触发一次MonitorGC就再好不过了。
  • 5、重新标记(Final ReMark)

    • 目标:GC事件中第二次(也是最后一次)STW阶段,目的是完成老年代中所有存活对象的标记。
    • 标记范围:Young Gen + Old Gen
    • 线程:GC线程独占执行
    • STW:触发Stop-The-World
    • 特点:速度较慢,可以说是整个CMS-Old GC的瓶颈点
    • 特殊:
      • 1、遍历新生代对象,重新标记
      • 2、根据GC Roots,重新标记
      • 3、遍历老年代的Dirty Card,重新标记
  • 6、并发清除(Concurrent Sweep)

    • 目标:根据标记结果清除垃圾对象。
    • 标记范围:Old Gen。
    • 线程:GC线程和应用线程也是并发执行
    • STW:不触发
    • 特点:速度一般。
  • 7、并发重置(Concurrent Reset)

    • 目标:重置CMS算法相关的内部数据, 为下一次GC循环做准备。
    • 线程:GC线程和应用线程也是并发执行
    • STW:不触发
    • 特点:速度一般。
7步图解:
三阶段:初始标记
二阶段:并发标记
三阶段:并发预清理
六阶段:并发清除

4、问题思考🤔:

【思考🤔】CMS里有两个需要STW的阶段:initial mark,remark、这两个标记有什么不一样么?使用的GC-Root一样么?
答案:不一样。
初始标记:使用的是常规的GC-Root(虚拟机栈栈帧中的局部变量表、本地方法栈native方法、方法区中类的静态属性和方法、方法区中常量等引用的对象)
重新标记:

  • 常规的GC-Root。
  • 新生代所有对象。
  • 遍历老年代的DirtyCard(ModUnionTable)。

【思考🤔】同时带来了另外一个问题,MonitorGC可没有遍历整个老年代,而是采用CardTable通过时间换空间的做法,CMS-OldGC为什么采用遍历新生代所有的对象呢?
        这就是YoungGen 与 OldGen存在明显的差异:

  • 老年代对象都是经历过多次GC回收♻️存活下来了,对象存在的变数极低。所以采用空间换时间效果较好。
  • 新生代对象属于变化特别快的区域,如果采用空间换时间,既浪费了空间,也没有提升性能。

【思考🤔】既然initial mark阶段+concurrent mark阶段已经扫果了young gen 为何还要再次Remark?

【思考🤔】CardTable与mod-union table有什么关系,都是干什么的?

相关文章

  • jvm 优化篇-(8)-跨代引用问题(RememberSet、C

    1、什么是跨代引用? 红色的线表示由虚拟机栈中发出的引用。显然B--->A、E--->F都是跨代引用。 2、跨代引...

  • JVM源码分析之跨代引用CardTable

    简书 占小狼转载请注明原创出处,谢谢 在上篇文章《JVM源码分析之YGC的来龙去脉》中提到了跨代引用dirty c...

  • jvm 相关阅读

    相关阅读 JVM性能优化1-JVM简介 JVM性能优化2-编译器 JVM性能优化3-垃圾回收 JVM性能优化4-C...

  • 为什么跨代引用是GC root

    昨日,有人在一个JVM群里问了一个问题,为什么跨代引用是gc root。这虽然是一个很简单的问题,但是其实涉及到了...

  • GC - 记忆集、卡表及写屏障

    记忆集与卡表 跨代引用 跨代引用是指新生代中存在对老年代对象的引用,或者老年代中存在对新生代的引用。 新生代引用老...

  • 01__JVM(1)

    什么是JVM:(jvm有跨平台性) java代码-->(翻译)class(字节码文件)-->机器上运行 JVM 代...

  • java虚拟机回收机制

    ps: 参考 jvm机制 jvm的新生代里为什么有两个Survivor区FullGC优化实战 JVM 垃圾回收器工...

  • ASO宝藏:80+ASO文章看完秒懂

    1、ASO优化基础 (8篇) 【思路】如何做好ASO优化(App运营推广必读) http://m.appcpu.c...

  • JVM调优

    JVM(Java虚拟机)优化大全和案例实战 JVM 优化经验总结 JVM 数据存储介绍及性能优化 JVM诊断...

  • Java 知识小集 第 1 期

    1. JVM 永久代中会发生垃圾回收么(JDK 8 之前)? 答案:会。永久代是 Hotspot 对 JVM 规范...

网友评论

      本文标题:jvm 优化篇-(8)-跨代引用问题(RememberSet、C

      本文链接:https://www.haomeiwen.com/subject/garenhtx.html