1、在程序運行時由CLR管理內存分配(Memory Allocation),程序啓動時,操做系統會爲每個線程申請一個獨立的棧內存,用於存儲方法的局部變量、參數和返回值等;CLR會爲進程申請一個連續的內存空間做爲託管堆內存,用於存儲引用類型對象和類型對象等;函數
1.託管堆主要包含兩部分:存儲引用類型對象的GC堆(GC Heap)和存儲類型對象的加載堆(Loader Heap),其中GC堆分爲小對象堆(Small Object Heap,SOH,<85000byte的對象)和大對象堆(Larage Object Heap,LOG,>=85000byte的對象);加載堆不受GC控制,生命週期從建立到應用程序域被卸載;
2.CLR在申請託管堆內存時,會維護一個指向下一個對象內存地址的指針,當在託管堆中分配新對象時,會經過該指針添加值來爲對象分配所需的內存,所以在託管堆中分配內存和在棧內存中分配內存的速度基本同樣快;性能
2、在棧上分配值類型的變量時,若是值類型所佔的空間不足當前系統的位數時,會分配當前系統位數的內存空間,例如在64位系統上分配的int類型的變量佔用64位,即8個字節;對於引用類型地址也是這樣,即32位系統上引用類型地址佔用4個字節,64位系統上則佔用8個字節;測試
//在64位系統上測試: unsafe { int num1 = 10; int num2 = 20; MyClass myClass = new MyClass(); int num3 = 30; Console.WriteLine((int)&num1); Console.WriteLine((int)&num2); //與num1地址相差8個字節 Console.WriteLine((int)&num3); //與num2地址相差16個字節 }
3、在使用運算符new建立引用類型對象或裝箱操做等在託管堆上建立對象時,CLR所作的主要操做有:優化
1.計算類及全部基類中聲明的全部實例字段所須要的字節數,還有兩個開銷成員(Overhead Member)的字節數:同步塊索引(Sync Block Index)和類型對象指針(Type Object Pointer);
※同步塊索引爲線程同步提供支持,也被稱爲對象頭字節(Object Header Word);
※類型對象指針存儲該對象的類型對象所在的內存地址,也被稱爲方法表指針(Method Table Pointer);
2.從託管堆中分配計算所獲得的字節數,全部字節初始化爲0;
3.初始化對象的類型對象指針和同步塊索引;
4.調用對應的實例構造函數,初始化實例字段,執行自定義構造函數中的其它操做;
※優先調用直接基類中的實例構造函數,直接基類中的實例構造函數又會調用其直接基類中的實例構造函數,最終最早調用的是基類System.Object中的實例構造函數;
5.返回新建對象的引用;spa
注:32位系統中,同步塊索引和類型對象指針分別佔4個字節,佔用的總空間大小會進行4字節倍數的對齊,同時即便類型定義中沒有實例字段,也會至少佔用4個字節,即最小佔用內存空間12字節;
注:64位系統中,同步塊索引和類型對象指針分別佔8個字節,佔用的總空間大小會進行8字節倍數的對齊,同時即便類型定義中沒有實例字段,也會至少佔用8個字節,即最小佔用內存空間24字節;操作系統
注:CLR在託管堆中連續分配多個對象時,這些對象在內存中也是連續存儲的;線程
注:可使用WinDbg查看具體的內存分配狀況;指針
注:CLR高度優化了託管堆上內存的分配和釋放,大多數狀況下,在堆內存上分配類實例與在棧內存上分配結構實例的性能並沒有顯著差別;code
若是您以爲閱讀本文對您有幫助,請點一下「推薦」按鈕,您的承認是我寫做的最大動力!對象
做者:Minotauros
出處:https://www.cnblogs.com/minotauros/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。