半?yún)^(qū)復(fù)制算法

前言

半?yún)^(qū)復(fù)制算法的目的也是為了更好的緩解內(nèi)存碎片問題庸娱。對比于標(biāo)記-壓縮算法, 它不需要遍歷堆內(nèi)存那么多次,節(jié)約了時間谐算,但是它也帶來了一個主要的缺點(diǎn)臣樱,那就是相比于標(biāo)記-清除和標(biāo)記-壓縮垃圾回收器,它的可用堆內(nèi)存減少了一半。同時對于大對象飘蚯,復(fù)制比標(biāo)記的代價更大暴凑。所以半?yún)^(qū)復(fù)制算法更一般適合回收小的凯傲,存活期短的對象。

三色抽象法

在我們深入半?yún)^(qū)復(fù)制算法原理前,我們需要了解下什么是三色抽象法缘厢。對于一個對象伊者,垃圾收集器可以將其標(biāo)記為灰色,黑色和白色中的一種多律,每種顏色代表不同的含義相味,

  1. 灰色 - 表示垃圾收集器已經(jīng)訪問過該對象,但是還沒有訪問過它的所有孩子節(jié)點(diǎn)。
  2. 黑色 - 表示該對象以及它的所有孩子節(jié)點(diǎn)都已經(jīng)被垃圾收集器訪問過了。
  3. 白色 - 表示該對象從來沒有被垃圾收集器訪問過,這就是非可達(dá)對象带族。

三色抽象法也可以用在標(biāo)記-清除算法和標(biāo)記-壓縮算法跋理。當(dāng)垃圾收集結(jié)束后,可達(dá)對象都被標(biāo)記為黑色,非可達(dá)對象都被標(biāo)記為白色,不會有灰色對象存在浦夷。在半?yún)^(qū)復(fù)制算法里懈息,我們也采用了三色抽象法來標(biāo)記對象姑宽。

算法原理

之所以叫半?yún)^(qū)復(fù)制,是因為它將堆內(nèi)存對半分為兩個半?yún)^(qū),只用其中一個半?yún)^(qū)來進(jìn)行對象內(nèi)存的分配,如果在這個半?yún)^(qū)內(nèi)存不夠給新的對象分配了,那么就開始進(jìn)行垃圾收集舆声,將這個半?yún)^(qū)中的所有可達(dá)對象都拷貝到另外一個半?yún)^(qū)中去,然后繼續(xù)在另外那個半?yún)^(qū)進(jìn)行新對象的內(nèi)存分配。半?yún)^(qū)復(fù)制算法中比較常見是Cheney算法。

下面是復(fù)制算法的偽代碼:

atomic collect():
    flip()
    scan <- free
    for each fld in Roots
        process(fld)
    while not isEmpty(worklist)
        ref <- remove(worklist)
        scan(ref)

flip():
    fromspace, tospace <- tospace, fromspace
    top <- tospace+extent  //界定堆內(nèi)存的邊界
    free <- tospace

scan(ref):
    for each fld in Pointers(ref)
        process(fld)

process(fld):
    fromRef <- *fld
    if fromRef != null
        *fld <- forward(fromRef) //將可達(dá)對象復(fù)制后的地址寫到原對象的位置上奥邮,當(dāng)作遷移地址
    
forward(fromRef):
    toRef <- forwardingAddress(fromRef) //讀取該位置上對象的遷移地址
    if toRef == null //如果該位置上的對象沒有遷移地址蘸朋,那就說明它還沒有被復(fù)制,需要復(fù)制到tospace中去
        toRef <- copy(fromRef)
    return toRef
    
copy(fromRef):
    toRef <- free 
    free <- free + size(fromRef)
    move(fromRef, toRef) //從fromRef位置復(fù)制對象到toRef位置上
    forwardingAddress(fromRef) <- toRef  //將地址toRef寫到fromRef位置上的對象中去
    add(worklist, toRef)
    return toRef

remove(worklist):
    ref <- scan
    scan <- scan + size(scan)
    return ref

實際上半?yún)^(qū)復(fù)制算法的實現(xiàn)跟標(biāo)記-壓縮算法的實現(xiàn)差不多, 都是采用的深度遍歷算法贞奋,理解該算法的關(guān)鍵點(diǎn)是,怎么計算可達(dá)對象的遷移地址(forwardingAddress) - 看copy(fromRef)方法的實現(xiàn)癌蚁, 以及怎么更新對象間的引用關(guān)系。

半?yún)^(qū)復(fù)制算法的過程如下:


復(fù)制算法
復(fù)制算法

我們假設(shè)A,B對象是根對象复唤。

  1. 首先先交換左右半?yún)^(qū)(ToSpace, FromSpace), 同時設(shè)置free指針和top指針。
  2. 遍歷處理根對象A,B穆桂。先將A對象復(fù)制到free指針指向的位置,同時將A對象復(fù)制后的地址(遷移地址)寫到原先A對象所在的位置萤衰,圖中虛線的箭頭表示∩崛牛可以看到A對象已經(jīng)被collector訪問過了,但是還沒有訪問其孩子節(jié)點(diǎn)阱表,所以將其標(biāo)為了灰色爱致。緊接著scan,free指針繼續(xù)向前移動忘朝。
  3. 由于是深度遍歷算法局嘁,緊接collector會先遍歷處理A對象所引用的對象C晌畅,當(dāng)發(fā)現(xiàn)對象C沒有遷移地址時剩岳,說明它還沒有被復(fù)制,由于它又是可達(dá)對象,所以接著collector會將它復(fù)制到當(dāng)前free指針指向的位置潮峦,即對象A后面嘱腥。對象C復(fù)制完后,會用其復(fù)制后的地址來更新A原先對C的引用拘悦,同時也寫到原先C對象所在的地址上齿兔。
  4. 接著collector會處理對象C的孩子節(jié)點(diǎn)(深度遍歷算法),由于對象C沒有引用任何對象础米,于是對象C的處理結(jié)束分苇,將其標(biāo)記為黑色。然后collector接著處理A對象的另外一個孩子節(jié)點(diǎn)E對象屁桑,處理方式跟處理對象C一致医寿。
  5. 對象E也沒有孩子節(jié)點(diǎn),collector也將其標(biāo)識為黑色掏颊。
  6. 到目前為此糟红,A對象也全部處理結(jié)束了,于是collector將其標(biāo)識為黑色乌叶,然后接著去處理對象B盆偿。當(dāng)復(fù)制B對象結(jié)束后,發(fā)現(xiàn)B對象所引用的對象C有遷移地址准浴,于是就更新其對對象C的引用事扭,使其指向FromSpace半?yún)^(qū)中對象C的遷移地址 - 即C對象復(fù)制后所在ToSpace的地址。這個情況下就不需要再次復(fù)制對象C了乐横。
  7. 當(dāng)所有的可達(dá)對象都從FromSpace半?yún)^(qū)復(fù)制到ToSpace半?yún)^(qū)后求橄,垃圾收集結(jié)束今野。新對象的內(nèi)存分配從free指針指向的位置開始進(jìn)行分配。

其實罐农,從垃圾收集過程中對象的移動順序來看条霜,collector將相鄰的對象都復(fù)制在相近的位置上,它屬于前面我們在標(biāo)記-壓縮算法里所說的“線性順序”涵亏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宰睡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子气筋,更是在濱河造成了極大的恐慌拆内,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宠默,死亡現(xiàn)場離奇詭異麸恍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搀矫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門抹沪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瓤球,你說我怎么就攤上這事采够。” “怎么了冰垄?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長权她。 經(jīng)常有香客問我虹茶,道長,這世上最難降的妖魔是什么隅要? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任蝴罪,我火速辦了婚禮,結(jié)果婚禮上步清,老公的妹妹穿的比我還像新娘要门。我一直安慰自己,他們只是感情好廓啊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布欢搜。 她就那樣靜靜地躺著,像睡著了一般谴轮。 火紅的嫁衣襯著肌膚如雪炒瘟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天第步,我揣著相機(jī)與錄音疮装,去河邊找鬼缘琅。 笑死,一個胖子當(dāng)著我的面吹牛廓推,可吹牛的內(nèi)容都是我干的刷袍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼樊展,長吁一口氣:“原來是場噩夢啊……” “哼呻纹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起滚局,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤居暖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后藤肢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體太闺,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年嘁圈,在試婚紗的時候發(fā)現(xiàn)自己被綠了省骂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡最住,死狀恐怖钞澳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涨缚,我是刑警寧澤轧粟,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站脓魏,受9級特大地震影響兰吟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茂翔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一混蔼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧珊燎,春花似錦惭嚣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谋国,卻和暖如春载矿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工闷盔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弯洗,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓逢勾,卻偏偏與公主長得像牡整,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子溺拱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

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

  • 一. 垃圾回收的意義 在C++中逃贝,對象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對...
    Stan_Z閱讀 1,924評論 0 25
  • JVM架構(gòu) 當(dāng)一個程序啟動之前迫摔,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū))沐扳,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,648評論 0 7
  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,446評論 17 311
  • 轉(zhuǎn)載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,353評論 1 56
  • 原文閱讀 前言 這段時間懈怠了句占,罪過沪摄! 最近看到有同事也開始用上了微信公眾號寫博客了,挺好的~給他們點(diǎn)贊纱烘,這博客我...
    碼農(nóng)戲碼閱讀 5,952評論 2 31