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

2020-07-10  本文已影响0人  tianlang136520
死神-露琪亚

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个步骤
重点步骤解读:
7步图解:
三阶段:初始标记
二阶段:并发标记
三阶段:并发预清理
六阶段:并发清除

4、问题思考🤔:

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

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

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

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

上一篇 下一篇

猜你喜欢

热点阅读