托管代码可是享受CLR提供的服务(安全检测,垃圾回收)不需要自己完成这些操作。托管代码是一种中间语言,运行在CLR上。托管代码独立与平台和语言,能更好的实现不同语言平台之间的兼容。
托管代码与非托管代码 https://pan.baidu.com/s/1KkxFyuSYQDxQ-aWzTkHWzw?pwd=sct2
C# 托管堆和垃圾回收器GC https://pan.baidu.com/s/1Y8nkLO2408EKWyWweH1iJw?pwd=ewpt
什么是垃圾回收?
在创建对象的时候程序会给对象分配内存空间,但是空间不是无限的,所以需要对已经不再使用的对象(垃圾)进行内存空间的回收(释放),这个过程叫垃圾回收。
在C#中垃圾回收是自动完成的,程序员不需要手动实现,但是这个过程对程序性能会产生影响,那么什么时候会触发垃圾回收?
- 物理内存地址不够时,由OS通知程序
- 堆上对象的内存超过了某个规定的阈值
- 手动调用GC.Collect方法
C#将堆分为大对象堆和小对象堆,大对象堆中的对象一般不进行释放,通常释放的是小对象堆中的内存空间
C#将静态字段、局部变量、CPU 寄存器、GC 句柄和终结队列等作为根(root),使用DFS或BFS算法进行遍历,并将被遍历的对象标记,并清除未被标记的对象,然后将其进行压缩,以便释放出连续的内存空间,压缩完成后,将其放在托管堆中,并根据其生存长短分成3代。
C#根据对象的生存长短将其分为三代:
- 第0代,这是生存时间最短的一代,垃圾回收经常回收这里的对象,对于没有回收的对象,将其升级为第一代。
- 第1代,这是和第二代之间的缓冲代,在第0代中没有被回收的对象会被升级为第1代,垃圾回收较少次数的回收这里的对象
- 第2代,这里存放的基本都是大对象,第一代中没有被回收的对象会被放到第2代
C#中 GC机制托管代码?
.Net所指的托管只是针对内存这一个方面,并不是对于所有的资源;因此对于Stream,数据库的连接,GDI+的相关对象,还有Com对象等等,这些资源并不是受到.Net管理而统称为非托管资源。而对于内存的释放和回收,系统提供了GC-Garbage Collector,而至于其他资源则需要手动进行释放。
一个引用类型对象所占用的内存需要被GC回收,需要先成为垃圾。那么.Net如何判定一个引用类型对象是垃圾呢,.Net的判断很简单,只要判定此对象或者其包含的子对象没有任何引用是有效的,那么系统就认为它是垃圾。
可以知道析构函数只能被GC来调用的,那么无法确定它什么时候被调用,因此用它作为资源的释放并不是很合理,因为资源释放不及时;但是为了防止资源泄漏,毕竟它会被GC调用,因此析构函数可以作为一个补救方法。而Close与Dispose这两种方法的区别在于,调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象被销毁了,不能再被使用,以通过调用GC.Collect();来强制GC进行垃圾回收。