并发标记算法


CardTable 由于做YGC时 可能会出现Old区的引用指向y区,那么需要扫描整个old区,效率非常低 所以JVM设计CardTable,将y区和o区分成一个一个card(区分是否有引用指向y区),如果一个o区cardTable中有对象指向y区,那么就将它设为Dirty,下次扫描时,只需要扫描dirtyCard
cardTable 只有一个是card的集合 里面是01的位图 0代表没有对象指向y区 1 代表有对象指向y区

Cset(collectionSet) 那些需要被回收的分区的集合(也就是card为1时有引用指向y区的集合) 分区可以来自伊甸 s区 或者o区
Rset(RememberedSet)
  region 里面都有一块区域(hashSet)记录了其他region中的对象到本region的引用,
 使得垃圾回收不需要扫描整个堆栈找到谁引用了当前分区中的对象,只需要扫描Rset即可


假如我要回收这块region 那么不需要扫描整个堆栈 因为这个region中有Rset,记录着所有引用了我当前回收的region的对象,如果没有 ,那么直接回收

YGC何时触发?
  伊甸区空间不足
  多线程并行执行
FGC何时触发?
old区空间不足
System.gc()
G1是否会产生FGC?如果G1产生FGC 应该如何做?
  会 当对象分配不下了就会产生FGC
  解决方法:
    1扩内存
    2提高CPU性能
    3降低MixedGC的触发阈值 让MixedGC尽早发生(默认值45%)

CMS和G1都是用的三色标记算法
  把对象在逻辑上分成三种颜色
    1 黑色  自身和成员变量均以标记完成
    2 灰色  自身被标记 但是成员变量为被标记
    3 白色  未被标记的对象

 

 在并发标记过程(remark 阶段)中 什么情况下容易发生漏标?以下两种情况必须同时发生  就会出现漏标的情况

  1  在并发标记过程中  有一个黑色对象引用指向白色对象

  2  灰色对象不在指向白色对象

  此时这个D是正常对象 但是漏标无法找到 当成垃圾回收了

解决并发标记产生漏标问题

  1 increment update 增量更新  关注引用的增加  把黑色重新标记为灰色  下次重新扫描属性   CMS算法实现

  2 SATB snapshot at the beginning 关注引用的删除   当B->D 消失时,要把这个引用推到GC的堆栈,保证D还能被GC扫描到   G1算法实现

    2.1 GC里面会有一个栈 这个栈中装着灰色对象指向白色对象的引用 如果B->D引用消失掉  还是可以在栈中找到  重新扫描栈中的引用即可

 为什么G1使用SATB?

   1 increment update  之前已经标记过得 还是要重新扫描 当这个黑色标记的引用很多,那么效率较低

  SATB 将那些之前改变过的 那些堆栈中的引用 直接扫描一遍

   2 为了配合Rset

  如果灰色 到 白色消失,如果黑色 没有指向 白色,引用会被push到堆栈,

  下次扫描时拿到这个引用,由于Rset的存在,不需要扫描整个堆去查找指向白色的引用,效率较高

 

 

posted @ 2022-04-30 16:25  花心大萝卜li  阅读(86)  评论(0)    收藏  举报