GC-标记清除算法(mark-sweep)

前一篇-GC算法基础相关概念

GC标记-清除算法

分为两个阶段

  • 标记阶段:把所有活动对象做上标记的阶段。
  • 清除阶段:把那些没有标记的对象(非活动对象)回收的阶段。

通过这两个阶段就可以令不能利用的内存空间重新得到利用。

伪代码如下:

mark_sweep() {
    mark_phase() //标记阶段
    sweep_phase() //清除阶段
}

假设我们执行GC前堆的状态示意图如下:


执行GC前堆的状态

标记阶段

简单概况: 标记阶段就是“遍历对象并标记”的处理过程

伪代码如下:

mark_phase() {
    for(r: $roots) {
        mark(*r)
    }
}

标记阶段中,为所有活动对象打上标记。其中活动对象是通过遍历、递归根(roots)直接引用的对象。

mark() 函数功能如下:

mark(obj) {
    if(obj.mark == FALSE) { //检查对象标记状态
        obj.mark = TRUE     //将标记置为TRUE
        for (child : children(obj)) {
            mark(*child) //递归标记引用的对象
        }
    }
}

标记操作会对对象中的mark标志位进行处理:

设置标志位的处理

标记阶段结束后,堆的状态如下:

标记阶段结束后状态

清除阶段

清除阶段会遍历整个堆,并回收没有打上标记的对象(垃圾对象)。使其能再次得到利用。

伪代码:

sweep_phase() {
    sweeping = $heap_start //堆起始位置
    while(sweeping < $heap_end) { //遍历堆
        if(sweeping.mark == TRUE) {
            sweeping.mark = FALSE   // 重置标记状态
        } else {
            sweeping.next = $free_list //加入到空闲链表
            $free_list = sweeping
        }
        sweeping += sweeping.size //移动指针到堆中下一个对象的头
    }
}

相关说明:

  1. sweeping: 用来遍历堆的指针,每移动一次增加当前sweeping.size个大小。
  2. size域: 存储对象大小(字节数)的域,与mark域一样,事先定义在对象头中。
  3. $free_list: 名为空闲链表的单向链表,遍历堆时会将非活动对象加入到空闲链表中。后续分配新对象时,通过遍历这个空闲链表来找到分块。
  4. next域: 只有在生成空闲链表及从空闲链表中取出分块时才会使用到,因此不需要额外定义一个next域,实际上是对象最初始的域(field1)。即给field1取的别名为next。与C语言中union 联合体概念相同。 (有点难于理解)

清除阶段完成后堆状态如下:

清除阶段结束后堆状态

总结: 清除阶段程序会遍历所有堆,进行垃圾回收。因此,花费的事件与堆大小成正比。堆越大,清除阶段花费的时间越长。

分配

分配指将回收的垃圾进行再利用。即当mutator申请分块时,将合适大小的分块分配给muator。实际操作是通过搜索空闲链表并寻找大小合适的分块。

伪代码:

new_obj(size) {
    chunk = pick_chunk(size, &free_list) {
        if(chunk != NULL) {
            return chunk //返回分块
        }
        else {
            allocation_fail() //分块失败
        }
    }
}

其中pick_chunk()函数用于遍历$free_list空闲链表,寻找大于等于size的分块。

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

推荐阅读更多精彩内容