.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的字段值。

相关文章
相关标签/搜索