|
系列文章導(dǎo)航:
.NET Discovery 系列之一--string從入門(mén)到精通(上)
.NET Discovery 系列之二--string從入門(mén)到精通(勘誤版下)
.NET Discovery 系列之三--深入理解.NET垃圾收集機(jī)制(上)
.NET Discovery 系列之四--深入理解.NET垃圾收集機(jī)制(下)
.NET Discovery 系列之五--Me JIT(上)
.NET Discovery 系列之六--Me JIT(下)
.NET Discovery 系列之七--深入理解.NET垃圾收集機(jī)制(拾貝篇)
關(guān)于.NET垃圾收集器(Garbage Collection),Aicken已經(jīng)在“.NET Discovery 系列”文章中有2篇的涉及,這一篇文章是對(duì)上2篇文章的補(bǔ)充,關(guān)于“.NET Discovery 系列”文章索引請(qǐng)見(jiàn)本文結(jié)尾。
第一節(jié).垃圾回收算法與完整收集(Full GC)
垃圾收集器就是跟蹤所有被引用到的對(duì)象,整理對(duì)象不再被引用的對(duì)象,回收相應(yīng)的內(nèi)存,它使用“標(biāo)記與清除”算法,分兩步回收對(duì)象:
Step 1.Mark-Sweep :從應(yīng)用程序的root出發(fā),利用相互引用關(guān)系,遍歷其在Heap上動(dòng)態(tài)分配的所有對(duì)象,指明需要回收的對(duì)象,標(biāo)記出那些存活的對(duì)象,予以標(biāo)記。
Step 2.Compact: 對(duì)內(nèi)存中存活的對(duì)象進(jìn)行移動(dòng),修改它們的指針,使之在內(nèi)存中連續(xù),這樣空閑的內(nèi)存也就連續(xù)了,即完成了內(nèi)存釋放工作,也解決了內(nèi)存碎片問(wèn)題,這個(gè)過(guò)程也可以成為指針的壓縮。
垃圾收集器一般將托管堆中的對(duì)象分為3代,這可以通過(guò)調(diào)用GC.MaxGeneration得知,對(duì)象按照存在時(shí)間長(zhǎng)短進(jìn)行分代,最短的分在第0代,最長(zhǎng)的分在第2代,第2代中的對(duì)象往往是比較大的,第二代空間被稱作Large Object Heap,對(duì)于2代對(duì)象的回收,與第0、1代回收方式相比最大的不同在于,沒(méi)有了指針移動(dòng)的壓縮過(guò)程。
圖1 對(duì)象的回收
如上圖所示,左邊的區(qū)域?yàn)榈谝淮蜧C時(shí)的結(jié)構(gòu),需要注意的是GC標(biāo)記的是那些存活的對(duì)象,而不是需要回收的,所以第一次回收,對(duì)象B、D沒(méi)有被標(biāo)記,所以被回收了,之后GC移動(dòng)了對(duì)象內(nèi)存指針,使空間連續(xù)。
接下來(lái)看中間的部分,第二次GC開(kāi)始了,C對(duì)象沒(méi)有被標(biāo)記,所以被回收了,接下來(lái)A、D、F三個(gè)對(duì)象被壓縮,形成連續(xù)的內(nèi)存空間,并且形成了第1、2、3代區(qū)域。
接下來(lái)看最右邊的部分,D對(duì)象沒(méi)有被標(biāo)記,由于D對(duì)象處于第2代中,所以回收D對(duì)象后,GC沒(méi)有啟動(dòng)壓縮步驟,因?yàn)閷?duì)于大對(duì)象的指針移動(dòng),資源耗費(fèi)成本很高。
對(duì)于第2代的GC稱為Full GC,新分配的對(duì)象在第0代(0代空間最大長(zhǎng)度通常為256K),按地址順序分配,它們通常是一些局部變量;第1代(1代空間最大長(zhǎng)度通常為2 MB)是經(jīng)過(guò)0代垃圾收集后仍然駐留在內(nèi)存中的對(duì)象,它們通常是一些如表單,按鈕等對(duì)象;第2代是經(jīng)歷過(guò)幾次垃圾收集后仍然駐留在內(nèi)存中的對(duì)象,它們通常是一些應(yīng)用程序?qū)ο蟆?/p>
可見(jiàn)一次Full GC需要的資源是最多的,可能是幾秒或十幾秒。
托管堆的內(nèi)存分配以段(Segment)為單位,CLR啟動(dòng)時(shí)通常為GC Heap創(chuàng)建2個(gè)段,分別用來(lái)存儲(chǔ)第0、1代對(duì)象和第2代對(duì)象,以下是通過(guò)Windbg工具查看到的GC Heap情況:
圖2 WinDbg 查看GC Heap情況
可以看出,GC堆被分成了兩個(gè)段,三代,每代起始地址十進(jìn)制差值為12。
在理解方面需要注意的是,GC回收的是程序中的引用類型,值類型是保存在堆棧之中,當(dāng)值類型對(duì)象出了作用域后會(huì)自動(dòng)釋放內(nèi)存----即彈棧,不需要垃圾收集器管理。
第二節(jié).GC的工作模式
GC的工作模式分3種,Workstation GC with Concurrent GC off、 Workstation GC with Concurrent GC on、Server GC ,在.NET 2.0以上版本可以通過(guò)修改Config文件來(lái)改變GC工作模式,例如啟用Server GC:
<configuration>
<runtime>
<gcServer enabled="true" />
</runtime>
</configuration>
NET技術(shù):.NET Discovery 系列之七--深入理解.NET垃圾收集機(jī)制(拾貝篇),轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。