【C#基礎】初探.Net內存分配原理

基本概念

CLR:公共語言運行時,類似Java的jvm,是直接建立在OS上的虛擬環境,主要任務是管理代碼運行。CLR現在支持幾十種現代的編程語言爲它編寫代碼,然後以一種中間語言(Intermediate Langeoage,IL)代碼的形成被執行。

.Net CLR非常詳細講解了clr原理東西。

線程堆棧:用於分配值類型實例。堆棧主要由操作系統管理,而不受垃圾收集器的控制,當值類型實例所在方法結束時,其存儲單位自動釋放。執行效率高,但存儲容量有限。

GC堆:用於分配小對象實例。如果引用類型對象的實例大小小於85000字節,實例將被分配在GC堆上,當有內存分配或者回收時,垃圾收集器可能會對GC堆進行壓縮。

LOH堆:用於分配大對象實例。如果引用類型對象的實例大小不小於85000字節時,該實例將被分配到LOH堆上,而LOH堆不會被壓縮,而且只在完全GC回收時被回收。

TypeHandle(類型句柄):指向對應實例的方法表,每個對象創建時都包含該附加成員,並且佔用4個字節的內存空間。我們知道,每個類型都對應於一個方法表,方法表創建於編譯時,主要包含了類型的特徵信息、實現的接口數目、方法表的slot數目等。

NextObjPtr:由託管堆維護的一個指針,用於標識下一個新建對象分配時在託管堆中所處的位置。CLR初始化時,NextObjPtr位於託管堆的基地址

分配原則

.Net中的資源分爲託管資源(受clr管理)和非託管資源(不受clr管理),取決於變量的數據類型,託管資源被存放在託管堆和堆棧中。

託管資源數據類型分爲值類型和引用類型,關於兩者的聯繫,之前的博客 【傻傻分不清楚】C#值類型、引用類型 做了比較。

值類型實例

對於值類型的實例,CLR在運行時有兩種分配方式:(1) 如果該值類型的實例作爲類型中的方法(Method)中的局部變量,則該實例被創建在線程棧上;(2) 如果該值類型的實例作爲類型的成員,則該實例作爲引用類型(引用類型在GC堆或者LOH上創建)的實例的一部分,被創建在GC堆上

    public class Test1  
    {  
        private int i;  
    //上面(2)中的情況,生成Test的實例的同時,int類型的實例i被創建在GC堆上  
        public Test1()  
        {  
            byte b =0;  
    //(1)中的情況,byte類型的實例b被創建在執行這段代碼的線程棧上  
        }  
    }  

引用類型實例

對於引用類型的實例,CLR在運行時也有兩種分配方式:(1) 如果該引用類型的實例的Size<85000Byte,則該實例被創建在GC(Garbage Collection)堆(當CLR在分配和回收對象時,GC可能會對GC堆進行壓縮);(2) 如果該引用類型的實例的Size>=85000byte,則該實例被創建在LOH(Large Object Heap)上(LOH不會被壓縮)。

    public class Test2  
    {  
        private int[] intArr;  
        public Test2()  
        {  
            private Object o = new Object();  
    //引用o存在線程棧上,它指向GC堆上的Object實例  
            intArr = new int[21250];  
    //符合(2)中的Size條件,int數組的實例被創建在LOH上  
        }  
    }  

有大神寫的博客,.NET下的內存分配機制做了非常詳細的分析!

發佈了45 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章