




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第C#內存管理CLR深入講解(下篇)《上篇》中我們主要討論的是程序集(Assembly)和應用程序域(AppDomain)的話題,著重介紹了兩個不同的程序集加載方式獨占方式和共享方式(中立域方式);以及基于進程范圍內的字符串駐留。這篇將關注點放在托管對象創建時內存的分配和對大對象(LO:LargeObject)的回收上,不對之處,還望各位能夠及時指出。
一、從類型(Type)與實例(Instance)談起
在面向對象的世界中,類型和實例是兩個核心的要素。不論是類型和實例,相關的信息比如加載到內存中,對應著某一塊或者多塊連續或者不連續的內存。那么對類型和實例的內存分配時如何進行的呢?對象是狀態和行為的組合體,所以從.NETFramework的角度來看類型,它只具有兩種類型的成員字段和方法(實際還有嵌套類型),前者表示狀態,后者表示行為。類型是對元數據的描述,而實例則是符合該元數據描述的單個個體。同一個類型下的所有實例具有相同的行為,它們通過狀態值的不同得以區分。所以內存中的實例(本篇所說的實例指代引用類型的實例)表示的是字段值,而內存中的類型表示的則是類型成員結構的元數據。很多人都知道,當我們創建一個對象的時候,CLR會在GC堆(Heap)中開辟一塊連續的內存空間保存字段值。那么類型信息又是保存在那塊內存上呢?
實際上,類型信息保存在另一堆上,我們稱之為加載器堆(LoaderHeap)。每一個應用程序域都具有各自的加載器堆,即包括我們創建的普通應用程序域,也包括《上篇》中提到的三個特殊應用程序域:系統程序域、共享程序域和默認程序域。如果說GC堆是實例的容器,那么基于應用程序域的加載器堆就是類型的容器。CLR采用按需加載(這里指的是類型,不是程序集)、及時編譯的運行機制。當某個類型被第一次使用的時候,CLR試圖加載該類型。如果該類型對應的程序沒有獨自地加載到本應用程序域中,或者沒有通過中立域的形式加載到共享程序域中,它會按照相應的方式加載程序集(在這里我們假設采用獨占方式加載)。然后,將使用到的這個類型加載到本應用程序域的加載器堆中。
加載器堆維護著自應用程序域創建以來使用過的所有類型記錄,它們對應著一個特殊的對象方法表(MethodTable)。當程序第一次執行到某個方法的時候,CLR會定位到方法表中該條目,獲取相關信息進行JIT編譯。所以如果某個類型在加載器堆中的方法表的某個條目至少被執行一次,它就會指向一段JIT編譯后的機器指令。
二、實例內存分配不僅限于GC堆
到現在為止,我們知道了類型和實例分別分配于基于應用程序域的加載器堆和GC堆中,那么CLR的內存分配僅僅限于這兩堆嗎?當然不是,除了這兩堆以及默認的進程堆,還有額外兩堆,一是存放JIT編譯后機器指令的JIT堆(JITHeap),另一個則是專門用于大對象的大對象堆(LOH:LargeObjectHeap)。下圖反映了CLR主要維護的這些個不同的堆。
對于大對象堆,在本文后續部分還會講述,在這里我們需要先了解CLR認為怎樣的對象是大對象。當我們實例化一個對象的時候,如果該對象大于或者等于85,000字節(這種對象一般是數組,一般對象不會這么大),CLR將認為是大對象并被放到LOH中,否則放到GC堆中。這里有一點需要讀者注意的是,作為垃圾回收器的GC并不僅僅限于針對GC堆中對象的回收,LOH中的對象的回收工作通過在GC的管轄之下。所以從某種意義上講:你可以將之前提到的GC堆理解為SOH(SmallObjectHeap),或者稱之為狹義GC堆,而將廣義GC堆理解為SOH+LOH。
三、實例對類型的引用
實例是類型的實例,實例和它所對應的類型需要維持一種聯系。反映在內存中,就以為著分配在GC堆或者是LOH中的對象具有一個對位于加載器堆中該類型的方法表的引用。實例對類型的引用通過一個特殊的對象來維系TypeHandle。我們舉個例子,在如下一段簡單的對象實例化代碼中,我先后實例化了四個對象:字符串ABC、System.Object對象、自定義Bar對象和具有85000個元素的字節數組。
stringstrInstance="ABC";
objectobjectInstance=newobject();
BarbarInstance=newBar()
byte[]largeObjInstance=newbyte[85000];
當上面的程序執行后,圍繞著實例化的四個對象和類型信息,在內存中將會具有如下一個關系。最左邊的是現成調用棧中的上述四個變量,對于字符串類型的strInstance,由于《上篇》所講述的關于字符串駐留機制,最后總的字符串被分配到系統程序域中;Object和Bar類型的objectInstance與barInstance由于是小于85000字節的小對象,所以被分配到GC堆中。objectInstance通過TypeHandle指向位于共享程序域中System.Objhect類型對應的方法表(因為定義該類型的mscorlib程序集以中立域的方式加載),而barInstance得TypeHandle指向的基于Bar類型的方法表則位于默認程序域中(因為程序域默認采用獨占的方式加載)。元素個數為85000的字節數組largeObjInstance屬于大對象,直接分配到LOH中。largeObjInstance的TypeHandle指向的基于System.Byte[]類型的方法表,該System.Byte[]類型同樣定義在mscorlib程序集中,所以該方法表同樣存在于共享程序域的加載器堆。
四、LOH中的對象如何被回收
了解GC的讀者應該都知道CLR采用基于代齡(Generation)的垃圾回收機制。代齡,個人覺得是一個很準確的詞語,它充分體現了設計者用于表現不同的對象具有不同生命周期的意思。所有對象分三代,即G0、G1和G2,這實際上代表了三個不同的連續的內存塊。輩分越高,表明時間越久;輩分越低,被掃蕩(GC回收)的頻率就越高。關于基于代齡的垃圾回收機制,限于篇幅,就說到這里。我們的重點是GC采用怎樣的機制對LOH的對象進行回收。
到目前為止,對于LOH和GC堆中的對象,除了大小之外,我們好像沒有覺得它們之間有何不同。實際上,將大對象放在LOH中,目的在于對其實施特殊的回收機制。關于垃圾收回,我們應該有這樣的認知:回收的成本是和對象的大小基本成正向關系,對象越大,回收成本就越大。所以我們不能對大對象頻繁地實施垃圾回收,實際上CLR是將LOH對象當成最高代齡的對象。也就是說,針對LOH的回收工作是和GC堆中G2一并進行的。換句話說,當G2或者LOH的剩余空間低于某個限度,針對它們的垃圾回收便被觸發。關于LOH的垃圾回收機制,我們可以通過一個非常簡單的程序來驗證。
classProgram
staticWeakReferenceSmallObjRef;
staticWeakReferenceLargeObjRef;
staticvoidMain(string[]args)
SetValues();
GC.Collect(0);
Console.WriteLine("GC.Collect(0)");
Console.WriteLine("SmallObjRef.Target==null{0}",SmallObjRef.Target==null);
Console.WriteLine("LargeObjRef.Target==null{0}\n",LargeObjRef.Target==null);
GC.Collect(1);
Console.WriteLine("GC.Collect(1)");
Console.WriteLine("LargeObjRef.Target==null{0}\n",LargeObjRef.Target==null);
GC.Collect(2);
Console.WriteLine("GC.Collect(2)");
Console.WriteLine("LargeObjRef.Target==null{0}\n",LargeObjRef.Target==null);
staticvoidSetValues()
SmallObjRef=newWeakReference(newbyte[84000]);
LargeObjRef=newWeakReference(newbyte[85000]);
}
輸出結果:
GC.Collect(0)
SmallObjRef.Target==nullTrue
LargeObjRef.Target==nullFalse
GC.Collect(1)
LargeObjRef.Target==nullFalse
GC.Collect(2)
LargeObjRef.Target==nullTrue
在上面的代碼中沒,我創建了兩個WeakReference對象,它們的Target分別被設置成byte[84000]和byte[85000]。按照我們上面關于對大
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 燃氣管網老化更新改造項目初步設計
- 老舊小區海綿城市建設項目實施方案
- 老舊小區改造項目初步設計
- 城市排污渠管徑擴容項目投資計劃書
- 教師教育技術應用創新大賽
- 新能源汽車充電設施補貼資金申請政策變化趨勢報告
- 2025年高速公路智能交通系統與智能停車解決方案融合報告
- 2025年高速公路智能交通系統與智能交通信號燈結合分析
- 肝膽護理業務學習
- 醫院三級護理流程圖解
- 基于單片機的智能臺燈控制系統的設計14000字【論文】
- (高清版)DB13(J)∕T 8557-2023 建設工程消耗量標準及計算規則(房屋修繕建筑工程)
- 2024云南省曲靖市陸良縣城鄉公交服務有限公司招聘(17人)筆試參考題庫附帶答案詳解
- 2025-2030年中國智能眼鏡行業市場市場現狀供需分析及投資評估規劃分析研究報告
- 2025年全國高考物理試題及答案
- 無人機飛行器編程基本知識試題及答案
- 國有企業違法犯罪課件
- 鉗工安全測試題及答案
- 預制菜加工采購合同協議
- 國家開放大學電大24153丨學前衛生學基礎(統設課)期末終考題庫
- 鐵路貨運基礎知識課件
評論
0/150
提交評論