1.CLR:公共语言运行时,就是IL(中间语言)的运行环境;安装.net Framewrok的时会安装CLR
2.堆栈内存分配: CLR进行内存的分配
值类型分配在栈中,变量和值都是在线程栈中(结构体是输出值类型,结构体默认继承system.valuetype,所以不能继承其他类了,结构体不能有无参构造函数,不能继承或者被继承)
引用类型分布在堆上,变量是存在栈中,值是在堆中
3.string类型
//string字符串内存分配 {string student = "大山";//开辟一块内存,放下"大山”,返回一个引用string student2 = student;student2 = "App";//改了student2的值,但不是修改内存,string字符串的内存是不可变的,不可变是因为享元,可能是多个变量指向同一个字符串//字符串变化了,多个变量都会受到影响,还因为堆里面的内存是连续分配的,如果变长度,会导致大量数据的移动//赋值其实是new string(app) ,重新开辟内存,返回引用//这时 student 的值依然是“大山”; }{string student = "大山";string student2 = "app";student2 = "大山";Console.WriteLine(object.ReferenceEquals(student,student2)); //结果输出true,clr内存分配字符串的时候,会查找相同值,有就重用了}
4.垃圾回收:
值类型出现在线程栈中,每次调用都有线程栈,用完自己就结束
引用类型出现在堆中,全局就一个堆,空间有限,所以需要进行垃圾回收,堆是连续分配的(数组),
GC发生在new的时候, new一个对象时,会开辟内存,看看空间够不够,不够的话就要GC了,发现内存不够,就去遍历堆中的对象,标记访问不到,然后启动一个线程来清理内存;
移动标记了的对象,其他挪动,然后整齐摆放,所以这个时候全部线程停止,不允许操作内存
但是析构函数 会单独的处理,它会把这些对象放入一个队列单独处理,但是不知道什么时候去调用析构函数,析构函数主要时用来释放非托管资源,是clr自动执行的
静态不会回收:如下所示
class GCDemo{private static Student _Student = new Student() //静态的不可能被回收,静态持有的引用也不会被回收 {Id = 123,Name = "jj"};public static void Show(){{Student student = _Student;Class @class = new Class(){};student.Class = @class;}{GC.Collect();//主动GC ,用于定时任务,执行一次后就不执行了,所以需要手动GC }}}
5.GC的2个优化策略:
一.分级策略:
首次GC前全部对象都是0级 ;
第一次GC后,还保留的对象叫1级;
回收先找0级对象,如果空间还不够,再去找1级对象,这之后还存在的对象就变成2级;
0级不够,1级也不够,2级还不够就内存溢出了
二.大对象策略:
如果大于某个值的对象85K,单独管理,用的时链表,避免频繁的内存移动
6.Dispose(); 只有实现了IDIsposable方法,才能使用using关键字;
在用完对象后,我们主动执行Dispose方法,当时可以使用using的快捷方式
internal class Student:IDisposable{public int Id { get; internal set; }public string Name { get; internal set; }public object Class { get; internal set; }public virtual void Dispose()//提供主动释放方式 {//通知垃圾回收机制不再调用析构器GC.SuppressFinalize(this);}~Student()//保证垃圾回收时,一定会把非托管资源释放 {}}