垃圾回收機制

原理
http://www.jb51.net/article/75292.htm
找到不再被使用的變量,然後釋放其佔用的內存,但這個過程不是時時的,因爲其開銷比較大,所以垃圾回收器會按照固定時間間隔週期性的執行

IE6的垃圾回收是根據內存分配量運行的,當環境中存在256個變量、4096個對象、64k的字符串任意一種情況的時候就會觸發垃圾回收器工作,

不再使用的變量也就是生命週期結束的變量,當然只可能是局部變量,全局變量的生命週期直至瀏覽器卸載頁面纔會結束。局部變量只在函數的執行過程中存在,而在這個過程中會爲局部變量在棧或堆上分配相應的空間,以存儲它們的值,然後在函數中使用這些變量,直至函數結束,而閉包中由於內部函數的原因,外部函數並不能算是結束。
回收方式
a.標記清除
當變量進入環境時,將這個變量標記爲“進入環境”;當變量離開環境時,則將其標記爲“離開環境”。標記“離開環境”的就回收內存
垃圾回收器在運行的時候會給存儲在內存中的所有變量都加上標記(當然,可以使用任何標記方式)。然後,它會去掉環境中的變量以及被環境中的變量引用的變量的標記(閉包)。而在此之後再被加上標記的變量將被視爲準備刪除的變量,原因是環境中的變量已經無法訪問到這些變量了。最後,垃圾回收器完成內存清除工作,銷燬那些帶標記的值並回收它們所佔用的內存空間。
(前端小白,如有錯誤,歡迎指正~~)
b.引入計數(低級瀏覽器)
當變量聲明,第一次賦值時記爲1,然後當這個變量值改變時,記錄爲0,將計數爲0的回收
IE中有一部分對象並不是原生js對象。例如,其內存泄露DOM和BOM中的對象就是使用C++以COM對象的形式實現的,而COM對象的垃圾回收機制採用的就是引用計數策略。因此,即使IE的js引擎採用標記清除策略來實現,但js訪問的COM對象依然是基於引用計數策略的。換句話說,只要在IE中涉及COM對象,就會存在循環引用的問題
var element = document.getElementById("some_element");
var myObject = new Object();
myObject.e = element;
element.o = myObject;
這個例子在一個DOM元素(element)與一個原生js對象(myObject)之間創建了循環引用。其中,變量myObject有一個名爲element的屬性指向element對象;而變量element也有一個屬性名爲o回指myObject。由於存在這個循環引用,即使例子中的DOM從頁面中移除,它也永遠不會被回收。
window.οnlοad=function outerFunction(){
 var obj = document.getElementById("element");
 obj.οnclick=function innerFunction(){};
};
這段代碼看起來沒什麼問題,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法會引用外部環境中德變量,自然也包括obj,是不是很隱蔽啊。
解決辦法
最簡單的方式就是自己手工解除循環引用,比如剛纔的函數可以這樣
1
2
myObject.element = null;
element.o = null;

1
2
3
4
5
window.οnlοad=function outerFunction(){
 var obj = document.getElementById("element");
 obj.οnclick=function innerFunction(){};
 obj=null;
};
將變量設置爲null意味着切斷變量與它此前引用的值之間的連接。當垃圾回收器下次運行時,就會刪除這些值並回收它們佔用的內存。


內存泄露
a.意外的全局變量引起的內存泄露
原因: 全局變量不會被回收
解決:使用嚴格模式避免
b.閉包引起的
原因: 活動對象被引用,使閉包內的變量不會被釋放
解決: 將活動對象賦值爲null
c.被清理的DOM元素的引用
原因: 雖然DOM被刪掉了,但對象中還存在對DOM的引用
解決: 將對象賦值爲null
d.被遺忘的定時器或回調
原因: 定時器內部實現閉包,回調也是閉包
解決: 清理定時器clearInterval、null

內存管理
1、什麼時候觸發垃圾回收?
垃圾回收器週期性運行,如果分配的內存非常多,那麼回收工作也會很艱鉅,確定垃圾回收時間間隔就變成了一個值得思考的問題。IE6的垃圾回收是根據內存分配量運行的,當環境中存在256個變量、4096個對象、64k的字符串任意一種情況的時候就會觸發垃圾回收器工作,看起來很科學,不用按一段時間就調用一次,有時候會沒必要,這樣按需調用不是很好嗎?但是如果環境中就是有這麼多變量等一直存在,現在腳本如此複雜,很正常,那麼結果就是垃圾回收器一直在工作,這樣瀏覽器就沒法兒玩兒了。
微軟在IE7中做了調整,觸發條件不再是固定的,而是動態修改的,初始值和IE6相同,如果垃圾回收器回收的內存分配量低於程序佔用內存的15%,說明大部分內存不可被回收,設的垃圾回收觸發條件過於敏感,這時候把臨街條件翻倍,如果回收的內存高於85%,說明大部分內存早就該清理了,這時候把觸發條件置回。這樣就使垃圾回收工作職能了很多
2、合理的GC方案
1)、Javascript引擎基礎GC方案是(simple GC):mark and sweep(標記清除),即:
  • (1)遍歷所有可訪問的對象。
  • (2)回收已不可訪問的對象。
2)、GC的缺陷
和其他語言一樣,javascript的GC策略也無法避免一個問題:GC時,停止響應其他操作,這是爲了安全考慮。而Javascript的GC在100ms甚至以上,對一般的應用還好,但對於JS遊戲,動畫對連貫性要求比較高的應用,就麻煩了。這就是新引擎需要優化的點:避免GC造成的長時間停止響應。

(前端小白,如有錯誤,歡迎指正~~)
發佈了36 篇原創文章 · 獲贊 19 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章