標記清除原理

照例貼出原文地址http://blog.csdn.net/yuezhiren/article/details/7948950#comments

標記清除算法是一種垃圾回收算法,它是第一個可以回收被循環引用的數據結構的垃圾回收算法.現在仍舊有許多常用的垃圾回收技術使用各種各樣的標記清除算法的變體.

        在使用標記清除算法時,未引用對象並不會被立即回收.取而代之的做法是,垃圾對象將一直累計到內存耗盡爲止.當內存耗盡時,程序將會被掛起,垃圾回收開始執行.當所有的未引用對象被清理完畢時,程序纔會繼續執行.

      標記清除算法又被叫做追蹤式垃圾收集器,這是因爲這種算法追蹤被程序所引用的所有對象.在程序中可以直接訪問的對象是指通過堆棧上的本地變量或者任意靜態變量說引用的對象.從垃圾回收的角度來看,這種對象,叫做根(roots).如果一個對象是被另外的可(直接或者間接)訪問的對象中的域引用,則這個對象可以被間接訪問.可訪問的對象被稱爲可用的(live),其他的對象被稱爲垃圾(garbage).

        標記清除算法由兩個階段組成: 

                第一階段,標記所有的可訪問對象.第一階段叫做標記階段.

                第二階段,垃圾收集算法掃描堆並回收所有的未標記對象.第二階段叫做收集階段.

        算法僞碼如下:

for each root variable r
    mark (r);
sweep ();

       爲了區分可用對象與垃圾對象,我們需要在每一個對象中記錄對象的狀態.因此,我們在每一個對象中加入了一個特殊的布爾類型的域,叫做marked.默認情況下,對象被創建時處於未標記狀態.所以,marked域被初始化爲false.

        對象p以及所有間接引用對象p的對象可以被下面的遞歸標記算法所標記:

void mark (Object p)

if (!p.marked)

p.marked = true; for each Object q referenced by p mark (q);


            在第二階段,標記清除算法掃描堆上的所有對象,主要是爲了定位所有未被標記的對象.分配給未被標記(即marked=false)的對象的存儲空間將會被回收.同時,可用對象的marked域將會被設置回false,以爲下一次標記清除算法時做準備.

void sweep ()

for each Object p in the heap

if (p.marked) p.marked = false else heap.release (p);

下面的圖示解釋了標記清除算法所執行的操作.圖示(a)爲垃圾回收執行之前的狀態.在這個例子中,是一個單一根變量.圖示(b)爲執行mark階段之後的狀態.在這個階段,所有可用的對象都被標記了.最後,在圖示(c)中,被標記爲false的對象被清理了,可用的對象(live)留了下來,並且所有可用(live)對象的marked域都被置成了false.


圖示 : 標記清除式的垃圾回收


因爲標記清除式的垃圾回收跟蹤了由根(root)訪問的所有對象,所以即使是在有循環引用時,它也可以正確的標記並執行垃圾回收工作.這是標記清除式垃圾回收與前一章所說的引用計數式垃圾回收相比,最主要的一個優勢.標記清除的第二個優點是,對於引用對象的常規操作不會產生任何的額外開銷.

        標記清除方法的主要缺點是,當垃圾回收算法執行時,正常的程序會被掛起.特別是,如果一個程序是交互式程序或者正在有一些實時運算時,這就會成爲一個問題.比如,一個正在進行垃圾回收的交互式程序會週期的無響應.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章