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/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。