GC-標記清除算法(mark-sweep)

前一篇-GC算法基礎相關概念

GC標記-清除算法

分為兩個階段

  • 標記階段:把所有活動對象做上標記的階段域帐。
  • 清除階段:把那些沒有標記的對象(非活動對象)回收的階段。

通過這兩個階段就可以令不能利用的內(nèi)存空間重新得到利用。

偽代碼如下:

mark_sweep() {
    mark_phase() //標記階段
    sweep_phase() //清除階段
}

假設我們執(zhí)行GC前堆的狀態(tài)示意圖如下:


執(zhí)行GC前堆的狀態(tài)

標記階段

簡單概況: 標記階段就是“遍歷對象并標記”的處理過程

偽代碼如下:

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

標記階段中踩衩,為所有活動對象打上標記恍涂。其中活動對象是通過遍歷、遞歸根(roots)直接引用的對象。

mark() 函數(shù)功能如下:

mark(obj) {
    if(obj.mark == FALSE) { //檢查對象標記狀態(tài)
        obj.mark = TRUE     //將標記置為TRUE
        for (child : children(obj)) {
            mark(*child) //遞歸標記引用的對象
        }
    }
}

標記操作會對對象中的mark標志位進行處理:

設置標志位的處理

標記階段結束后弃鸦,堆的狀態(tài)如下:

標記階段結束后狀態(tài)

清除階段

清除階段會遍歷整個堆听盖,并回收沒有打上標記的對象(垃圾對象)胀溺。使其能再次得到利用。

偽代碼:

sweep_phase() {
    sweeping = $heap_start //堆起始位置
    while(sweeping < $heap_end) { //遍歷堆
        if(sweeping.mark == TRUE) {
            sweeping.mark = FALSE   // 重置標記狀態(tài)
        } else {
            sweeping.next = $free_list //加入到空閑鏈表
            $free_list = sweeping
        }
        sweeping += sweeping.size //移動指針到堆中下一個對象的頭
    }
}

相關說明:

  1. sweeping: 用來遍歷堆的指針,每移動一次增加當前sweeping.size個大小皆看。
  2. size域: 存儲對象大胁治搿(字節(jié)數(shù))的域,與mark域一樣腰吟,事先定義在對象頭中无埃。
  3. $free_list: 名為空閑鏈表的單向鏈表,遍歷堆時會將非活動對象加入到空閑鏈表中毛雇。后續(xù)分配新對象時嫉称,通過遍歷這個空閑鏈表來找到分塊。
  4. next域: 只有在生成空閑鏈表及從空閑鏈表中取出分塊時才會使用到灵疮,因此不需要額外定義一個next域织阅,實際上是對象最初始的域(field1)。即給field1取的別名為next震捣。與C語言中union 聯(lián)合體概念相同蒲稳。 (有點難于理解)

清除階段完成后堆狀態(tài)如下:

清除階段結束后堆狀態(tài)

總結: 清除階段程序會遍歷所有堆氮趋,進行垃圾回收。因此江耀,花費的事件與堆大小成正比剩胁。堆越大,清除階段花費的時間越長祥国。

分配

分配指將回收的垃圾進行再利用昵观。即當mutator申請分塊時,將合適大小的分塊分配給muator舌稀。實際操作是通過搜索空閑鏈表并尋找大小合適的分塊啊犬。

偽代碼:

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

其中pick_chunk()函數(shù)用于遍歷$free_list空閑鏈表,尋找大于等于size的分塊壁查。

  • 如果找到和size大小相同的分塊觉至,則會直接返回該分塊;
  • 如果找到比size大的分塊睡腿,則將其分割成size大小的分塊和去掉size大小后剩余大小的分塊语御,并把剩余的分塊返回空閑鏈表。
  • 如果沒有找到合適的分塊席怪,則拋出分配錯誤应闯。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市挂捻,隨后出現(xiàn)的幾起案子碉纺,更是在濱河造成了極大的恐慌,老刑警劉巖刻撒,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骨田,死亡現(xiàn)場離奇詭異,居然都是意外死亡声怔,警方通過查閱死者的電腦和手機盛撑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捧搞,“玉大人,你說我怎么就攤上這事狮荔√テ玻” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵殖氏,是天一觀的道長晚树。 經(jīng)常有香客問我,道長雅采,這世上最難降的妖魔是什么爵憎? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任慨亲,我火速辦了婚禮,結果婚禮上宝鼓,老公的妹妹穿的比我還像新娘刑棵。我一直安慰自己,他們只是感情好愚铡,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布蛉签。 她就那樣靜靜地躺著,像睡著了一般沥寥。 火紅的嫁衣襯著肌膚如雪碍舍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天邑雅,我揣著相機與錄音片橡,去河邊找鬼。 笑死淮野,一個胖子當著我的面吹牛捧书,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播录煤,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鳄厌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了妈踊?” 一聲冷哼從身側響起了嚎,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廊营,沒想到半個月后歪泳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡露筒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年呐伞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎式。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡伶氢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘪吏,到底是詐尸還是另有隱情癣防,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布掌眠,位于F島的核電站蕾盯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蓝丙。R本人自食惡果不足惜级遭,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一望拖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挫鸽,春花似錦说敏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蚂夕,卻和暖如春迅诬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背婿牍。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工侈贷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人等脂。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓俏蛮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親上遥。 傳聞我的和親對象是個殘疾皇子搏屑,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容