在本章中,我們將介紹垃圾收集的概念,垃圾收集是.NET托管代碼平臺(tái)最重要的特性之一。 垃圾收集器(GC)管理內(nèi)存的分配和釋放。 垃圾收集器用作自動(dòng)內(nèi)存管理器。
- 我們不需要知道如何分配和釋放內(nèi)存或管理使用該內(nèi)存的對(duì)象的生命周期
- 每當(dāng)使用
new關(guān)鍵字聲明對(duì)象或?qū)⒅殿?lèi)型裝箱時(shí),都會(huì)進(jìn)行分配。分配通常非???。 - 當(dāng)沒(méi)有足夠的內(nèi)存分配一個(gè)對(duì)象時(shí),GC必須收集和處理垃圾內(nèi)存以使內(nèi)存可用于新的分配。
這個(gè)過(guò)程被稱(chēng)為垃圾收集。
垃圾收集的優(yōu)勢(shì)
垃圾收集提供以下好處(優(yōu)勢(shì)) -
- 在開(kāi)發(fā)應(yīng)用程序時(shí),不需要手動(dòng)釋放內(nèi)存。
- 它還有效地在托管堆上分配對(duì)象。
- 當(dāng)對(duì)象不再使用時(shí),它將通過(guò)清除內(nèi)存來(lái)回收這些對(duì)象,并將內(nèi)存保留為將來(lái)的分配。
- 托管對(duì)象自動(dòng)獲得干凈的內(nèi)容,所以它們的構(gòu)造函數(shù)不必初始化每個(gè)數(shù)據(jù)字段。
- 它還通過(guò)確保對(duì)象不能使用其他對(duì)象的內(nèi)容來(lái)提供內(nèi)存安全性。
垃圾收集的條件
垃圾收集在下列條件之一時(shí)發(fā)生:
- 當(dāng)系統(tǒng)的物理內(nèi)存較低時(shí)。
- 托管堆上分配的對(duì)象使用的內(nèi)存超過(guò)了可接受的閾值。該閾值在流程運(yùn)行時(shí)不斷調(diào)整。
GC.Collect方法被調(diào)用,在幾乎所有情況下,不必調(diào)用此方法,因?yàn)槔占鬟B續(xù)運(yùn)行。這種方法主要用于獨(dú)特的情況和測(cè)試。
階段過(guò)程
.NET垃圾收集器有3代,每一代都有自己的堆,用于存儲(chǔ)分配的對(duì)象。有一個(gè)基本的原則,判定大多數(shù)對(duì)象是短暫的還是長(zhǎng)期的。
1. 第一代(0)
- 在第
0代中,首先分配對(duì)象。 - 在這一代,對(duì)象通常不會(huì)超越第一代,因?yàn)樵谙乱淮卫占瘯r(shí),它們不再被使用(超出范圍)。
0代很快收集,因?yàn)樗嚓P(guān)的堆很小。
2. 第二代(1)
- 在第一代,對(duì)象有第二個(gè)機(jī)會(huì)空間。
- 在第
0代收集(通常是基于巧合的時(shí)機(jī))下壽命很短的對(duì)象會(huì)轉(zhuǎn)到第1代。 - 第一代集合也很快,因?yàn)樗年P(guān)聯(lián)堆也很小。
- 前兩堆仍然很小,因?yàn)閷?duì)象被收集或提升到下一代堆。
3. 第三代(2)
- 在第二代,所有的長(zhǎng)對(duì)象都是活動(dòng)的,它的堆可以長(zhǎng)得很大。
- 這一代的對(duì)象可以長(zhǎng)期存活下去,沒(méi)有下一代堆積對(duì)象可以進(jìn)一步推廣。
- 垃圾收集器有一個(gè)額外的堆,用于稱(chēng)為大對(duì)象堆(LOH)的大型對(duì)象。
- 它保留
85,000字節(jié)或更大的對(duì)象。 - 大對(duì)象并沒(méi)有分配到代代堆,而是直接分配給了LOH
- 第二代和LOH收集可能會(huì)花費(fèi)很長(zhǎng)時(shí)間運(yùn)行的程序或運(yùn)行大量數(shù)據(jù)的程序。
- 已知大型服務(wù)器程序在十幾個(gè)GB中堆積如山。
- GC采用各種技術(shù)來(lái)減少阻止程序執(zhí)行的時(shí)間。
- 主要方法是在后臺(tái)線程上盡可能多地執(zhí)行垃圾回收工作,而不會(huì)干擾程序執(zhí)行。
- GC還為開(kāi)發(fā)人員提供了一些方法來(lái)影響其行為,這對(duì)提高性能非常有用。