程序需要使用资源,比如文件、内存缓存区、屏幕空间、网络连接、数据库资源等; 在C#里, 万物皆对象,面向对象编程时,要使用这些资源则就需要为这些资源分配内存,我们可以理解为创建对象
那么从创建到销毁,对象的一生又是怎样的呢?
整理如图,主要可分为5步:
创建对象需要分配内存,那么这些内存又该怎么分配呢?
CLR 要求所有的对象都要从托管堆中分配;
那么托管堆又是怎么来的呢?
进程初始化时,CLR会划出一个地址空间区域作为托管堆;同时CLR维护一个指针--NextObjPrt;该指针指向下一个对象在堆中的分配位置;
最开始时NextObjPtr被设置为地址空间区域的基地址;
参照图:
托管堆的大小是不变的吗?
不是;
当托管堆被非垃圾对象填满后,CLR会为其分配更多的区域,该过程可重复直至整个进程的地址空间都被填满;
所以,应用程序的内存受进程的虚拟地址空间的限制,32位的进程最多分配1.5GB,64位进程最多分配8TB;
托管堆上分配对象又有什么优势呢?
从图中我们可以发现,对象是在托管堆【内存】上连续分配的,对象之间的引用,便就有了引用局部化【locality】,性能上则有了大大的提升,同时对象可全部驻留在CPU中,程序便能以惊人的速度对其进行访问【因为:避免了CPU执行操作时因为“缓存未命中”而被迫访问较慢的RAM】
托管堆不能无限扩大,因为内存是有限的,当内存不足时,又应该怎么办呢?
当程序尝试创建新对象,发现内存不足时,CLR会通过“垃圾回收”【GC】,来删除不必要的对象,清理内存
具体GC是怎么操作的,可参考改文章 https://www.cnblogs.com/Alicia-meng/p/13339990.html