.NET的堆和棧01,基本概念、值類型內存分配

當咱們對.NET Framework的一些基本面瞭解以後,實際上,仍是頗有必要了解一些更底層的知識。好比.NET Framework是如何進行內存管理的,是如何垃圾回收的......這樣,咱們才能寫出更高性能的程序。html

 

在.NET Framework中,有2個地方幫咱們保存管理數據:一個是"堆",也叫"託管堆",由.NET Framework的垃圾收集器(Garbage Collection, GC)管理;另外一個是"棧",也叫"線程堆棧",由操做系統直接管理。它們都寄宿在操做系統內存。性能

 

本篇主要包括:
■  什麼是"棧"
■  什麼是"堆"
■  值類型內存分配
    ※  在方法內的值類型內存分配
    ※  在引用類型內部的值類型內存分配
■  練習題   ui

 

  什麼是"棧"spa

 

能夠把"棧"想像成由下而上堆疊起來的盒子,值類型實例存儲於此。
1操作系統

 

在 應用程序中,每當調用一個方法,就至關於在"堆"上放上了一個盒子A,這時,應用程序只能使用處在"棧"最上方、剛被放上的這個盒子A,當方法執行結束, 至關於把最上方的盒子A扔掉。接下來,剛纔還在A下面的盒子B就處在"棧"的最上方了,因而應用程序又開始使用盒子B,以此類推。並且,每當把最上面的盒 子扔掉,其對應的內存也被自動釋放。線程

 

棧的優勢是執行效率高,缺點是存儲容量有限。指針

 

在.NET Framework中,全部派生於System.ValueType的就是值類型,值類型實例位於"棧"。值類型包括:
● bool
● byte
● char
● decimal
● double
● enum
● float
● int
● long
● sbyte
● short
● stuct
● uint
● ulong
● shortcode

 

  什麼是"堆"htm


能夠把"堆"想像成一些擺放無序的盒子,引用類型實例存儲於此。
2  對象

 

咱們能夠在任什麼時候候,使用任何盒子。咱們須要藉助垃圾收集器(Garbage Collection, GC)的自動回收機制或手動處理,以保證"堆"的盒子被及時回收。


另 外,根據引用類型實例的大小,"堆"分爲"GC堆"和"LOH(Large Object Heap)堆",當引用類型實例大小小於85000個字節的時候,實例被分配在"GC堆"上;當實例大小大於或等於於85000個字節的時候,實例被分配 在"LOH(Large Object Heap)堆"。

 

在.NET Framework中,全部派生於System.Object的就是引用類型,引用類型實例位於"堆"。引用類型包括:
● 類 class
● 接口 interface
● 委託 delegate
● object
● string

 

  值類型內存分配

  在方法內的值類型內存分配

public int Add(int x)
{    int result;
    result = x + 2;    return result;
}

 

一、在執行Add(int x)方法以前,方法參數x被存放到"棧"的頂部。
3

 

二、在"method table"中搜尋Add()方法,若是找不到,就讓JIT及時編譯再存放到"method table"中去。

 

三、開始執行Add(int x)方法,局部變量result也須要"棧"中的一些內存。
4

 

四、當方法執行完畢,先釋放result,再釋放x,線程堆棧指針從新指向。
5

 

  在引用類型內部的值類型內存分配

public class MyClass
{    public int MyValue;
}public MyClass Add(int x)
{
    MyClass result = new MyClass();
    result.MyValue = x + 2;    return result;
}

複製代碼

 

一、在執行Add(int x)方法以前,方法參數x被存放到"棧"的頂部。
3

 

二、在"method table"中搜尋Add()方法,若是找不到,就讓JIT及時編譯再存放到"method table"中去。

 

三、開始執行Add(int x)方法,執行MyClass result = new MyClass()
先在託管堆上建立一個MyClass的實例,而後在棧上開闢一塊空間並指向實例地址。
6

 

四、當方法執行完畢,在棧中由上到下依次釋放內存。
7

 

此時,在託管堆上的MyClass實例如何處理呢?

 

五、此時,垃圾回收器登場了,他在託管堆中搜尋那些再也不被引用的對象實例,而後實施回收。

 

  練習題

複製代碼

public int ReturnValue()
          {                int x = new int();
                x = 3;                int y = new int();
                y = x;      
                y = 4;          
                return x;
          }

複製代碼

結果是:3, 由於值類型x變量,在方法執行結束以前,一直存在於棧上。

 

複製代碼

public int ReturnValue2()
          {
                MyInt x = new MyInt();
                x.MyValue = 3;
                MyInt y = new MyInt();
                y = x;                 
                y.MyValue = 4;              
                return x.MyValue;
          }

複製代碼

結果是:4,由於,當經過y=x把x賦值給y時,其實是把x在託管堆上的地址賦值y,也就是,棧上的x和y都指向託管堆上的同一個對象實例,改變y的字段值,至關於改變x的字段值。

相關文章
相關標籤/搜索