垃圾回收
- 1. 托管和非托管资源
托管资源
由CLR管理的存在于托管堆上的资源
// Common Language Runtime (CLR) 译为「通用语言运行时」
关键点:由CLR管理,在托管堆上
托管资源的回收工作是不需要人工干预的,CLR会在合适的时候调用GC(垃圾回收器)进行回收
非托管资源
非托管资源是不由CLR管理
例如:Image Socket,StreamWriter, Timer,文件句柄,,GDI资源,数据库连接等等资源
非托管资源GC[Garbage Collection]是不会自动回收的,需要手动释放
- 2. 垃圾回收的目的
整理内存,回收不再使用的对象,释放内存以提高效率
- 3. 托管资源的垃圾回收
CLR的一个核心功能
垃圾回收
垃圾回收器
只回收托管堆中的内存资源,不回收其他资源(数据库连接、文件句柄、网络端口等)
//非托管资源GC[Garbage Collection]是不会自动回收的,需要手动释放
什么样的对象才会被回收?
答:没有变量引用的对象
什么时间回收?
- 去饭店吃饭,什么时候收盘子呢?
- 系统回收,具体何时回收垃圾由系统自行确定,并不是即时执行回收的
- 手动调用垃圾回收器GC.Collect();,不建议使用,垃圾回收时会会使程序暂停,影响程序性能
垃圾回收器中“代”的概念:
- 共3代:第0代、第1代、第2代
- 回收频率:第0代最高,其次第1代,再次第2代
- 越老的对象生存几率越大
- 第0代满则回收第0代;第1代满则回收第0代与第1代,不满则不回收;第2代是顶级代,超过第2代内存则会报内存溢出
标记-压缩回收机制
弱引用
- 问题:如果有一个比较耗费资源的对象,每次实例化都很麻烦,如果指向null后又使用了,则可以先到内存中找一找,看有没有回收,如果没回收则直接使用
- 解决:使用弱引用WeakReference对象(代码见备注)
- 弱引用:告诉GC可以回收,如果再次访问时还没有回收,则可以拿过来继续使用;如果回收了则获取不到了
- 使用情况[原因]:对象的创建比较耗费时间,如从数据库中取出来100条数据存入List中,这时List对象最好使用弱引用
//将对象存入弱引用:
Person p=new Person();
p.Age=18;
WeakReference wk=new Reference(p); //弱引用
P=null;
//从弱引用中获取对象:
object pnew=wk.Target;
if(pnew!=null)
{
Console.WriteLine((Person)pnew).Age);
}
else
{
Console.WriteLine("对象已经被回收!!!");
}
- 4. 非托管资源的垃圾回收
方法一:使用Dispose()方法
对象要继承IDisposable接口,也就会自动调用Dispose方法
推荐使用using语法进行使用,最终不用手动释放资源
方法二:使用Finalize()方法
允许对象在“垃圾回收”回收之前尝试释放资源并执行其他清理操作
此方法的本质就是析构函数