再谈HotSpot JVM GC机制中的写屏障

前言

在比较久之前的一篇文章《再谈JVM里的记忆集合》中,笔者曾经写了这么一段话:

HotSpot通过写屏障(write barrier)来维护卡表。我们已经知道,内存屏障的主要作用是防止指令重排序,它也是volatile关键字的基础。有了写屏障,JVM就可以保证引用发生改变时,对卡表中的卡做标记与访问内存的顺序不发生变化。在CardTableRS初始化时,所做的第一件事就是创建卡表需要的屏障集合(barrier set)……

为什么划掉了呢?(原文也已经划掉了)

在上文中,笔者犯了一个原则性的低级错误,即把Java内存模型中的内存屏障/内存栅栏(memory barrier/fence)与HotSpot GC机制中的写屏障(write barrier)混为一谈了,但这两者实际上毫无关系。Doug Lea大佬也在《JSR-133 Cookbook for Compiler Writers》一文中明确指出:

Memory barriers are unrelated to the kinds of "write barriers" used in some garbage collectors.

带来困扰,十分抱歉。

写屏障是个有些复杂的话题,准确来说,它在GC中的应用也有不止一处。下面先纠正错误,简单解释写屏障的概念,及其与卡表的关系。

写屏障与卡表

“写屏障”这个词虽然看起来高深,但是它的含义却相当naive——就是对一个对象引用进行写操作(即引用赋值)之前或之后附加执行的逻辑,相当于为引用赋值挂上的一小段钩子代码。

前文所述“HotSpot通过写屏障来维护卡表”,写屏障就是在将引用赋值写入内存之前,先做一步mark card——即将出现跨代引用的内存块对应的卡页置为dirty,如下图所示。

而之前提到过的JVM参数-XX:+UseCondCardMark,就是开启有条件的写屏障:在将卡页置为dirty之前,先检查它是否已经为dirty状态,如果已经是了,就不必再执行mark card动作,以避免虚共享。

写屏障除了用于维护卡表之外,在并行GC(如CMS、G1)中的并发标记阶段还有一个更重要的用途。下面以CMS垃圾收集器为例简单解说。

并行GC中并发标记的漏标隐患

我们已经知道,CMS垃圾收集器的执行分为以下6个阶段:

  1. 初始标记
  2. 并发标记
  3. 并发预清理
  4. 重新标记
  5. 并发清理
  6. 并发重置

其中,只有不带“并发”字眼的初始标记、重新标记两个阶段是stop-the-world的,其他4个阶段都是与用户线程(GC界的术语称作mutator)并行的,这符合CMS收集器追求最少STW时间与最高响应度的宗旨。

初始标记和并发标记阶段就是进行可达性分析。CMS的根搜索机制是深度优先的三色标记(tri-color marking)算法,属于基础知识,不再展开讲了。

初始标记阶段会只遍历GC Roots直接可达的那些对象,并压入标记栈(mark stack);并发标记阶段会逐一从标记栈中弹出对象,然后不断递归标记它们直接引用的对象,重复压入-弹出过程,直到标记栈为空。

在并发标记阶段,难点在于:用户线程并未停止,仍然在改变对象的引用关系。这有可能造成原本活动的对象被漏标,进而破坏GC的正确性。示例如下图所示。

(a) 搜索对象A的直接子对象,标记对象B为可达(灰色),并将B压入标记栈。此时A的直接子对象搜索完毕,标记为存活(黑色),将A弹出标记栈;

(b) (c) 与此同时,用户线程改变引用,让A引用C,并移除掉B对C的引用;

(c) 结果:无法再由B标记到C,但也无法由A标记到C(因为A已经出栈)。C虽然仍为活动对象,但被错判为非活动(白色)对象而被回收。显然这是无法容忍的。

事实上,不止是CMS,在其他任何并行的垃圾回收器中,都有对象漏标的隐患。Wilson指出,出现漏标的充要条件是以下两个情况同时发生:

  1. mutator使黑色对象直接引用了白色对象;
  2. mutator删除了从灰色对象到白色对象之间的所有引用路径。

强三色不变式与增量更新写屏障

为了解决漏标问题,需要破坏上文所述的两个情况,亦即强制回收器满足如下两个条件之一。

  • 强三色不变式:保证永远不会存在黑色对象到白色对象的引用(破坏情况1)。
  • 弱三色不变式:所有被黑色对象引用的白色对象都处于灰色保护状态,即直接或间接从灰色对象可达(破坏情况2)。

强/弱三色不变式都可以通过屏障技术来实现,并且在不同环境下有多种不同的屏障技术。CMS收集器采用增量更新(incremental update)写屏障实现强三色不变式,具体来讲,是Dijkstra等人提出的Dijkstra写屏障,其逻辑是:

拦截使黑色对象引用指向白色对象的mutate操作,强制被引用指向的白色对象置为灰色状态,并将其压入标记栈。

Dijkstra写屏障的逻辑用伪码表示如下。

write_barrier(obj, field, newobj) {
  if(newobj.mark == FALSE) {
    newobj.mark = TRUE
    push(newobj, $mark_stack)
  }
  *field = newobj
}

可见,之所以名为“增量更新”,是指写屏障会持续hook引用的插入和变更。下图示出了加入增量更新写屏障后,并发标记阶段引用发生更改的情况,可见对象C可以安全地存活了。

但是,增量更新写屏障无法探知堆外(如栈上)GC Roots的引用变化,所以CMS收集器在并发标记和预清理完成后,还得做一次重新标记,即再做一次根搜索。

The End

G1的解决思路与CMS又有不同,是采用了初始快照(snapshot-at-the-beginning, SATB)写屏障实现了弱三色不变式。G1垃圾收集器非常复杂,应该择日好好总结一下,今天就不提了。

明天早起搬砖,民那晚安。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352