.Net Framework垃圾收集具體算法詳解
.Net Framework是由微軟提供的一款基于.NET開發(fā)的基礎環(huán)境。不過在這個編程平臺下,我們還可以使用其他各種語言來進行代碼的編寫,大大提高了程序員的開發(fā)效率。在這里就先來了解一下.Net Framework垃圾收集的相關算法。#t#
1..Net Framework垃圾收集只有在第0代對象充滿時才會出現(xiàn)。
2.每組應用程序都有一組根,一個根是一個存儲位置,其中包含著一個指向引用類型的內存指針。同時,當JIT編譯器編譯一個方法的IL代碼時,除產(chǎn)生本地CPU代碼外,JIT編譯器還會創(chuàng)建一個內部表,該表的每個條目包含一個方法的本地CPU指令的字節(jié)偏移范圍,及該范圍中的一組包含跟的內存地址。
3.當垃圾收集器開始執(zhí)行時,它先假設應用程序中沒有一個根引用著托管堆中的對象。然后,遍歷所有的根,構造出一個包含所有可達對象的圖。任何不在該圖中的對象都將是應用程序不可訪問的對象 ,也是可以被執(zhí)行垃圾收集的對象。
為什么.Net Framework垃圾收集的功能如此強大,而ANSI C++沒有采用它?
這是因為垃圾收集器必須能夠識別出應用程序的根,并且還要找到所有的對象指針。非托管C++允許我們進行類型轉換,而無從知道它真正引用的對象是什么。在CLR中,托管堆總能知道一個對象的實際類型,從而使其元數(shù)據(jù)信息來判斷一個對象的哪些成員引用著其他的對象。
任何封裝了非托管資源的類型,例如文件、網(wǎng)絡鏈接、套接字、互斥體等,都必須支持一種稱作終止化(Finalization)的操作。終止化操作允許一種資源在它所占用的內存被回收之前首先執(zhí)行一些清理工作。
如果一個封裝了非托管資源的類型沒有定義Finalize方法,那么這些托管資源將得不到關閉,從而導致某種程度的資源泄露,直到進程結束,這些非托管資源才會被操作系統(tǒng)回收。
Finalize方法的問題在于我們不能確定它會在何時被調用,而且它不是公有方法,因此不能顯式調用它。
我們可以通過顯示調用Dispose方法來釋放對象所封裝的非托管資源。
調用Dispose或Close方法只是在一個確定的時刻對對象占用的非托管資源執(zhí)行清理操作而已,但不會控制托管堆中對象所使用的內存的生存期。這意味著我們在調用過Dispose或Close方法之后,對象的內存仍然存在,只是對象被執(zhí)行資源清理后,不能再成功執(zhí)行某些方法而已。
C#的using語句:編譯時,編譯器會自動產(chǎn)生一個try塊和一個finally塊,在finally塊中,編譯器會產(chǎn)生代碼將變量轉型為一個Idisposable接口,并調用其上的Dispose方法。
但我們應謹慎使用C#的using語句,避免過早的執(zhí)行了資源清理
垃圾收集器中代齡的工作機制:CLR的托管堆支持3個代齡,但初始化時,它會為這三代選擇3個閾值容量,選擇閾值容量是為了提高系統(tǒng)性能,閾值容量越大,垃圾收集執(zhí)行的頻率也就越低。
另外,CLR垃圾收集器還有一個自調節(jié)的能力,會學習應用程序的行為,調節(jié)閾值容量,從而改變.Net Framework垃圾收集執(zhí)行的頻率,提高系統(tǒng)性能。