日期:2014-05-17  浏览次数:20841 次

CLR回收疑问
看到一篇文章中说CLR回收是根据检查所有的根(静态字段、方法参数、局部变量、、),从而对托管堆中的对象进行标记。如下:
void TestMethod(){
     for (int i = 0; i < 10; i++)
     {
         Model m = new Model();//Model 为一个Class           
     }
}
1、m在栈中创建一次?
2、如果m在栈中出现一次,那么是在何时取消与new Model()之间的引用。
3、m与new Model()之间的应用取消时会再堆中清空new Model()在堆中所占的空间吗?如果不会根据CLR的回收机制,检查根的时候岂不是就忽略了i=0到i=8的new Model();如此,这一部分堆岂不是永远都不能被释放。
本人菜鸟,希望各位大虾多多指点。分给的少,不要介意哈。

------解决方案--------------------
1.m创建了10次
2.当本次循环的作用域结束后,m与Model对象之间的引用就清除了
3.变量和对象之间的引用清除后,何时回收对象,由GC决定。
------解决方案--------------------
m不但创建了10次,而是是在堆上,因为是class。
如果你循环1000次,没等出函数,gc就会开始回收之前创建的m了。
------解决方案--------------------
1. Model m = new Model();
m 分配在堆栈上,new Model这个实例分配在堆上,m只是指向 new Model,你的会创建10次

2.大括号为作用域,在for遍历中,每次过了下届的大括号时,这时,m变量在堆栈中被释放(自动),m就不再指向 堆中的new Model,按照你的代码,此时 是垃圾对象,还在托管堆中,等待 GC回收。

3.过了大括号,m已释放,new Model成为空引用,成为垃圾。i是在 堆栈中,过了作用域自动释放,
至于 new Model 等GC回收时释放,GC回收是不确定的,不知什么时候回收。

------解决方案--------------------
如果编译为release,这段代码直接被编译器给优化掉(删除),如果编译为debug,这段代码会执行指定的次数,但GC不会回收之前创建的m,除非CPU空闲或内存不够了,但你这里绝对不会内存不足。
------解决方案--------------------
是在托管堆上的 给你了个测试的例子
你把创建的M对象存在一个list里面然后分别调他们的getHashCode 看一样不?
其实是在堆上创建了10个对象 不是一个