CLR是公共语言运行库,Common Language Runtime)和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集),并保证应用和底层操作系统之间必要的分离。
垃圾回收的目的:提高内存利用率。机制:只回收托管堆中的内存资源,不回收其他资源(文件句柄,网络端口等)。
那些声明的整型、浮点型等变量会被垃圾回收机制处理吗?No.它们用完了是直接弹栈的,不需要去回收,而那些堆里的对象,如Person p = new Person();Object c = new Object()..除了栈里面有地址,内存里面还有数据,这些在堆中的内存数据,才会被垃圾回收机制处理掉。普通的变量,值类型,这些是不需要被垃圾回收的,用完了就直接弹栈。
也就是说,GC(垃圾回收机制):
1.只回收堆里面的内存,只回收引用变量,值类型不处理。
2.只回收内存资源,不回收其他资源。
举一个例子,就好像去吃饭,c/c++是吃完饭自己收盘子,c#是吃完饭,你不用收,服务员会自动帮你收盘子(但是不能保证总是在第一时间快速完美的收掉盘子)。
比如写了一个Person 类
Person a = new Person();
Person b = new Person();
a = b;//a 不再指向之前在堆中分配的内存,第一个new Person()分配的内存空间就可以被GC回收了。
又如:
List<Person> mylist = new List<Person>();
Person p = new Person(); //会被回收吗??
mylist.add(p);
p = null;
上面的new 出来的Person不会被回收,因为通过mylist[0]还是可以得到它的,就好像是有一根线还在牵着它,它不是断线的风筝,我的饭还没有吃完,我还在用盘子,所以服务员不可以回收我的盘子。
如果你想自己收盘子,可以调用GC.collect().但是一般不需要手动调用垃圾回收。因为在调用GC.collect的时候,会暂停其他线程,使程序性能降低!
一般不要手动调用垃圾回收,因为垃圾回收有一系列算法,需要移动对象等等,这是为了达到目的,需要暂停应用程序的其他处理,这时若频繁的调用垃圾回收反而影响性能。当然如果你很明确下一段代码很耗资源,可以调用GC.Collect()。
在垃圾回收中,有一个“代”的概念,共3代:第i代(i = 0,1,,2)。
各代的回收率:0>1>2。越老的对象,生存几率越大。.NET中的垃圾回收机制使用标记压缩:mark-and-compact。
第0代回收率最高,第1,2代只有当其所处的内存满了才回收,第2代如果满了,会扩大所分配的内存,如果到了不能再扩大的地步,则报错:out of memory。失去引用的对象内存空间会首先进入第0代。垃圾回收采用“代”的概念,避免了每次垃圾回收都便利所有的对象,减少了垃圾回收的时间。
在介绍一个例子,需要用到弱引用:WeakReference.
Person p = new Person();
p.age = 18;
WeakReference wk = new WeakReference(p); //弱引用,垃圾回收可以回收该对象,可以。
p = null; //当执行完这句话的时候,1.垃圾回收可以回收该对象了。2.通过弱引用可以访问到p ,如果调用GC.Collect(),则弱引用会被回收。
比如创建一个对象连接数据库,然后建立一个集合将所有的数据导入到集合中,当不连接的时候,这个集合对象就会被释放掉,这时可以尝试使用弱引用,你爱回收就回收,不想回收的话,更好,性能还可以提升一下,起到一个 >= 的效果,回收了就重新建一个。弱引用一般用在那些创建时比较耗时的对象上。