CLR VIA C# 阅读笔记和感悟(二)

GC垃圾回收:垃圾回收机制其实是对内存的碎片化管理,首先会暂停所有线程的执行,防止碎片化管理时,对象的状态被修改,然后遍历托管堆中的所有对象,删除没有变量引用的对象,并且移动堆中的所有对象的内存地址,删除对象之间的空隙,变成一块连续的内存,提高对象的引用效率,节省更多的内存空间,但这会导致之前变量保存的地址失效,因为之前保存的地址不再是是对象的起始地址了,所以CLR会根据堆中对象移动的偏移量修改之前变量保存的地址,使得变量保存的地址和对象的真实地址一致,然后恢复所有线程。

        垃圾回收采用了"代"的管理机制,第0代对象最容易被垃圾回收,第1代对象是在第0代对象清理中存活下来的对象,第2代对象保留的是第1代对象清理中存活下来的对象,其中第0代对象的清理最频繁,第2代对象的清理最慢,因为垃圾回收机制都是从第0代开始清理的。









        CLR会对托管堆进行3代的内存分配,只要内存使用查过预期就会执行垃圾回收,而重载了object类型Finalize方法的对象,在被标记为第0代对象后,本应是垃圾的它因为需要被执行Finalize重载而被引用到内部的一个终结器列表中,由此对象再次被引用,从而对象被复活了,并保存在第1代中,Finalize方法执行完后就再也没有谁引用它,所以第1代中执行垃圾回收时就会删除这个对象。借用书中的图来直观感受下:


AppDomain:程序启动后会告诉系统创建一个进程,进程中会包含进程一开始就会创建的AppDomain程序集容器,容器中包含了程序集中的各种类信息,也就是说我们的代码在运行时都是在AppDomain这个大环境中定义好,执行时交给CLR处理,代码执行到哪里CLR中的JIT编译器就动态编译到哪里,并把编译后的CPU指令缓存在内存中,然后以后的每次执行都是获取已缓存的CPU指令并交给CPU执行。这里给我的感觉是,本地软件exe运行时是把软件本身运行在内存中吗?其实不是的,软件运行只是系统创建一个进程的契机,系统只是把软件运行的必要信息读取到内存中,并动态编译执行而已,但一些附加二进制文件会被加载到内存中,比如音频图片等。一个进程可以包含有多个程序集容器,程序集容器之间是隔离的,不会对数据造成损坏。借用下书中的一张图来直观感受下:




版权声明:本文为博主原创文章~转载请注明出处


猜你喜欢

转载自blog.csdn.net/u014690615/article/details/80085964