- CLR垃圾回收器采用代(generation)机制,目前支持0、1、2三代:
- 新构造添加到堆的对象称为第0代。
- 经过对第0代的垃圾回收之后,第0代的幸存者被提升至第1代。
- 经过对第1代的垃圾回收之后,第一代的幸存者被提升至第2代
- CLR初始化时,会为每一代选择预算。第0代的预算约为256K,第1代预算约2M,第2代预算约10M。在实际使用过程中,垃圾回收器会用类似启发式算法调整各代的预算。
- 软件开始运行时,运行时会为每一个Generation预留一块连续的内存(这样说并不严格,但不影响此问题的描述),同时会保持一个指向此内存区域中尚未使用部分的指针P,当需要为对象分配空间时,直接返回P所在的地址,并将P做相应的调整即可
- .NET会将对象分成两种情况区别对象,一种是大小小于85000字节的对象,称之为小对象,它就对应于前面描述的一般情况;另外一种是大小在85000之上的对象,称之为大对象。在.NET中,所有大对象都是分配在另外一个特别的连续内存(LOH, Large Object Heap)中的,而且,每个大对象在创建时即属于G2,也就是说只有在进行Generation 2的垃圾回收时,才会处理LOH。而且在对LOH进行垃圾回收时不会压缩内存!更进一步,LOH上空间的使用方式也很特殊——当分配一个大对象时,运行时会优先尝试在LOH的尾部进行分配,如果尾部空间不足,就会尝试向操作系统请求更多的内存空间,只有在这一步也失败时,才会重新搜索之前无效对象留下的内存空隙
- 对象被标示为垃圾后会自动调用其Finalize方法,前提是对象重写了object的Finalize方法
- GC.SuppressFinalize是说在垃圾回收的时候不执行这个对象的C#析构函数中的内容。
- Dispose()方法和Close()方法的区别:
- Dispose()方法除了释放资源之外,还会通知垃圾收集器对该对象不再需要执行终结操作(析构函数),它是通过调用GC.SuppressFinalize()方法来实现的,该方法通知垃圾回收器不在执行析构函数
- Close()方法一般不会这么处理,因此在调用了Close()方法的对象,依然会停留在终结队列中,即对象会被清除。因此,我们应该优先调用Dispose()方法。
- Dispose()方法不会将对象从内存上删除,它只是让对象释放非托管资源,这意味着如果释放的是仍被使用的对象,那么可能会遇到一些问题,因此,我们不应该释放那些仍然被程序其他地方引用的对象。
时间: 2024-12-11 18:47:58