垃圾收集器用來在.NET中進行內(nèi)存管理,特別是它可以恢復正在進行中的應用程序需要的內(nèi)存。到目前為止,WINDOWS平臺已經(jīng)使用了兩種技術(shù)來釋放進程向系統(tǒng)動態(tài)請求的內(nèi)存:
讓應用程序代碼負責釋放內(nèi)存是低級、高性能的語言使用的技術(shù),例如C++。這種技術(shù)很有效,而且可以讓資源在不需要的時候就釋放(一般情況下),但最大的缺點是頻繁出現(xiàn)錯誤,請求內(nèi)存的代碼還必須明確通知系統(tǒng)它什么時候不再需要該內(nèi)存,但是這很容易被遺漏,從而導致內(nèi)存泄露。
盡管現(xiàn)代的開發(fā)環(huán)境提供了幫助檢測內(nèi)存泄露的工具,但它們很難追蹤錯誤,因為直到內(nèi)存已經(jīng)大量泄露從而已經(jīng)使WINDOWS拒絕為進程提供資源時,它們才會發(fā)揮作用。到那個時候,由于對內(nèi)存的需求,會使整個計算機變的相當緩慢。
維護引用計數(shù)是COM對象采用的一種技術(shù),其方法是每個COM組件都保留一個計數(shù),記錄客戶機目前對它的引用數(shù)。當這個計數(shù)下降到0的時候,組件就會自己刪除自己(侯杰曾經(jīng)在《程序員》雜志撰寫過自己刪除自己的組件的文章),并釋放相應的內(nèi)存和資源,它帶來的問題是仍然需要客戶機通知組件它們已經(jīng)完成了內(nèi)存的使用。只要有一個客戶機沒有這么做,對象就仍然駐留在內(nèi)存中。在某些方面,這是比C++內(nèi)存泄露更加嚴重的問題,因為COM對象可能存在于它自己的進程中,從來不會被系統(tǒng)刪除(在C++內(nèi)存泄露問題上系統(tǒng)至少可以在進程中斷時候釋放所有的內(nèi)存)。
。NET運行庫采用的方法是垃圾收集器,這是一個程序,其目的是清理內(nèi)存,方法是所有動態(tài)請求的內(nèi)存都分配到堆上(這對所有的語言都一樣,但是在。NET中,CRL維護它自己的托管堆,以供。NET應用程序使用)當。NET檢測到給定進程的托管堆已滿,需要清理時,就調(diào)用垃圾收集器。垃圾收集器處理目前代碼中的所有變量檢查對存儲在托管上的對象的引用確定哪些對象可以從代碼中訪問——既哪些對象有引用。沒有引用的對象就不能再從代碼中訪問,因而被刪除。JAVA就使用與此類似的垃圾收集系統(tǒng)。
之所以在。NET中使用垃圾收集器,是因為中間語言已用來處理進程。其規(guī)則要求,第一,不能引用已有的對象,除非復制已有的引用。第二,中間語言是類型安全的語言。在這里,其含義是如果存在對對象的任何引用,該引用中就有足夠的信息來確定對象的類型。
垃圾收集器機制不能和諸如非托管C++的語言一起使用,因為C++允許指針自由地轉(zhuǎn)換數(shù)據(jù)類型。
垃圾收集器的一個重要方面是它是不確定的。換而言之不能保證什么時候會調(diào)用垃圾收集器;。NET運行庫決定需要它時就可以調(diào)用它(除非明確調(diào)用垃圾收集器)。但可以重寫這個過程,在代碼中調(diào)用垃圾收集器。