瀏覽器的垃圾回收機制


垃圾回收機制

垃圾收集器必須跟蹤哪個變量有用哪個變量沒用,對於不再有用的變量打上標記,以備將來收回其占用的內存,內存泄露和瀏覽器實現的垃圾回收機制息息相關, 而瀏覽器實現標識無用變量的策略主要有下兩個方法:

引用計數

跟蹤記錄每個值被引用的次數。當聲明一個變量並將引用類型的值賦給該變量時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變量,則該值的引用次 數加1.相反,如果包含對這個值引用的變量又取得另外一個值,則這個值的引用次數減1.當這個值的引用次數變成0時,則說明沒有辦法訪問這個值了,因此就 可以將其占用的內存空間回收回來。

如: var a = {};     對象{}的引用計數為1
        b = a;          對象{}的引用計數為 1+1
        a = null;       對象{}的引用計數為2-1

所以這時對象{}不會被回收;

IE 6, 7 對DOM對象進行引用計數回收, 這樣簡單的垃圾回收機制,非常容易出現循環引用問題導致內存不能被回收, 進行導致內存泄露等問題, 如:

demo1:
var btn = $("button");
btn.onclick = function(){
   //當這里也可以訪問到btn,說明function內部存在btn的引用
};

demo2:

function a () {
    var x = { };
    var y = {};
    x.a = y;
    y.a = x;
}
a();

函數a執行完后,本來x, y對象都應該在垃圾回收階段被回收, 可是由於存在循環引用,也不能被回收。
    

標記清除(mark-and-sweep)

到2008年為止,IE,Firefox,Opera,Chrome和Safari的javascript實現使用的都是標記清除式的垃圾收集策略(或類似的策略),只不過垃圾收集的時間間隔互有不同。

標記清除的算法分為兩個階段,標記(mark)和清除(sweep). 第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除

markFromRoots():
    worklist <- empty
    for each fld in Roots
        ref <- *fld
        if ref != null && isNotMarked(ref)  
           setMarked(ref)
           add(worklist,ref)
           mark()
mark():
    while not isEmpty(worklist)
          ref <- remove(worklist)  
          for each fld in Pointers(ref)  
                child <- *fld
                if child != null && isNotMarked(child)
                   setMarked(child)
                   add(worklist,child)

sweep(start,end):
    scan <- start
   while scan < end
       if isMarked(scan)
          setUnMarked(scan)
      else
          free(scan)
      scan <- nextObject(scan)

atomic collect():
    markFromRoots()
    sweep(HeapStart,HeapEnd)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM