首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

obj=null;是否能让对象立刻释放,是否能加快对象释放,是否有必要加上?解决方法

2012-02-23 
objnull是否能让对象立刻释放,是否能加快对象释放,是否有必要加上?我这个喜欢闭门造车,所以很多论点都有

obj=null;是否能让对象立刻释放,是否能加快对象释放,是否有必要加上?
我这个喜欢闭门造车,所以很多论点都有可能是错误,于是放在这里和大家一起商讨一下。如果对各位造成什么误导的话,个人不请求原谅,你们爱报复就报复,爱打击就打击,我不嫌弃臭鸡蛋,当然更喜欢鲜花。。。好了,客套就到此为至。以下说说主题。

 昨天和一群友讨论内存回收的问题。突然有位自称IBM+移动的JAVA群友说在使用完对象后整个=null;这样对象可以加快翻译。。。并且经过IBM小组的严格测试。。。
汗一把,怀疑是难免的。后来看到坛子里也有讨论析构函数的,于是也发个帖。。

首先以,是否能让对象内存立刻回收 展开说法。。
  
  个人认为这是错误的:
设置对象null时执行,设置对象null只是段开了内存对象与引用句柄之间的引用关系,只是把引用转了个位,并没有让对象为null
翻译对象主分两块,一为非托管对象,二为托管对象。
先以非托管对象为例:这个我简单测试为"设置对象null只是段开了内存对象与引用句柄之间的引用关系"是正确的。。
测试Code

C# code
 static void OpenConnection(SqlConnection conn)        {            if (conn.State != ConnectionState.Open)                conn.Open();        }        static void TestUnManager()        {            try            {                for (int i = 0; i < 10; i++)                {                    SqlConnection conn = new SqlConnection("server=20080827-1517; User ID=sa;Password=cherry; database=InforSys; min pool size=2; max pool size=3");                    TimeSpan bts = DateTime.Now.TimeOfDay;                    OpenConnection(conn);                    TimeSpan ets = DateTime.Now.TimeOfDay;                    TimeSpan ts = bts - ets;                    Console.WriteLine(ts);                    //conn.Close();                    conn = null;                    Thread.Sleep(1000);                }            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);            }        }


基本来说,如果按照对象为null 的话,连接肯定是不存在的。实事是,连接在请求第5个的时候出exception,抛链接池已满。。


托管资源是否为一样?其实这个一般比较难测试,因为垃圾回收机制一般在内存进缺的时候会比较勤快,而且在申请内存方面也是很麻烦,
于是测试环境我为所有能关的服务都关了,内存为2G当前使用情况为581M的情况下测试,这样或许不会让垃圾回收器觉醒过来。。
但是内存申请也是个麻烦事,一开始使用StringBuilder来划内存,当然,效果肯定是没有的,后来只有采用粗鲁的手段从数据库大表里填充数据集。。这方法其实也很默哀,如果有更好方法的朋友可以告诉偶一下。。。。

测试CODE

C# code
 static void TestManager()        {            for (int i = 0; i < 10; i++)            {                GetTable();                            }        }        static void GetTable()        {                      using (SqlConnection conn = new SqlConnection("server=20080827-1517; User ID=sa;Password=cherry; database=InfoSys; min pool size=20; max pool size=100"))            {                SqlCommand cmd = new SqlCommand("select * from gtl_comp", conn);                using (SqlDataAdapter da = new SqlDataAdapter())                {                    DataTable dt = new DataTable();                    da.SelectCommand = cmd;                    da.Fill(dt);                    dt = null;//这分两个,一个有,一个没有                }            }                            }


分两种情况都执行了一下,发现内存的消耗情况基本相同,有dt=null的有时反而会多占用一点。。。
基本认为有没有是一个样,不能立刻对象释放。。(同在内存使用量不是很大的情况下)


以上测试比较简单,但我个人认为=null;是不能加快对象释放的。


最后一个为,是否有必要加上,受一坛子的帖启发来测试的。

MSDN原话:
 
垃圾回收器使用名为“终止队列”的内部结构跟踪具有 Finalize 方法的对象。每次您的应用程序创建具有 Finalize 方法的对象时,垃圾回收器都在终止队列中放置一个指向该对象的项。托管堆中所有需要在垃圾回收器回收其内存之前调用它们的终止代码的对象都在终止队列中含有项。



关键的是垃圾回收器在运行的时候会释放怎么样的对象?在我的理解里一直为当该对象没有任何引用时,垃圾回收器就运行该对象的析构,释放对象。。。

测试CODE
C# code
 public class Test    {        private string name;        public Test(string name)        {            this.name = name;            StringBuilder sb = new StringBuilder(10240000);            for (int i = 0; i < 102400; i++)                sb.Append(name+i);        }        ~Test()        {            Console.WriteLine(name+"执行到析构");        } static void Main(string[] args)        {            //TestUnManager();            //TestManager();            NotSetNull();            SetNull();                   }        static void NotSetNull()         {            for (int i = 0; i < 100; i++)            {                Test t = new Test("ojek"+i);            }        }        static void SetNull()        {            for (int i = 100; i < 200; i++)            {                Test t = new Test("ojek" + i);                t = null;            }        }    } 



执行两个方法,都会输出相关内容。。即,t=null和不加上这句,析构都会运行。。。

运行结果还有一点特色,输出的并不是按顺序排例的(我这并没有启动线程),这个其实也证明了垃圾回收器在释放对象的时候是无序的,即,不能确保对象释放时利用组合模式,从内向外或者从外向内释放。。。



然后这个不免产生疑惑: 变量或者说引用,其实也是对象,如果引用没有释放的时候,引用指几的对象当然是不会被垃圾回收器释放的。如果垃圾回收器先找到对象,不释放,再找到引用,释放,这样对象就得等垃圾回收器下一次运行的时候再回收了。。。如果通过大数据的测试,或许可以证明,把引用和对象一刀两断,或许能够加快对象的释放。。





即obj=null;还是可要的,当然,如果是非托管对象要先dispose()再断开对象与引用之间的关系。。


[解决办法]
up
个人觉得加不加=null没有什么影响,当然我没测试过,不能断言
[解决办法]
很强大
[解决办法]
很实在
[解决办法]
SqlConnection conn = new SqlConnection("server=20080827-1517; User ID=sa;Password=cherry; database=InforSys; min pool size=2; max pool size=3");

TimeSpan bts = DateTime.Now.TimeOfDay;
OpenConnection(conn);
TimeSpan ets = DateTime.Now.TimeOfDay;
TimeSpan ts = bts - ets;
Console.WriteLine(ts);
//conn.Close();
conn = null;
Thread.Sleep(1000);


这样不close 你的程序一会就完完, =null 有个屁用.
[解决办法]
IBM照道理不测试C#. 应该研究的是Java. 不过二者的垃圾回收机制应该是极度相似的。

从理论上来说:垃圾回收器的进程优先级非常低,所以导致回收速度很慢。
有些高性能程序还是需要自己来释放内存/资源,而不能等垃圾回收器来回收。
[解决办法]
本次赋值之后因为不能强制运行dispose所以不能及时释放内存

垃圾回收器会在下次回收内存时对堆内存中的对象进行回收
[解决办法]
=null应该不释放,再加上GC.Collect()才能控制释放,否则就要等自动的垃圾回收了!
[解决办法]
up
[解决办法]
按我的理解,每个对象都是一个气球,当你要某一个气球的时候,就把它吹大,然后用一根绳子系着,同一个气球有可能被多个人同时牵着,
它还没破的时候就一直占用空间(内存),GC相当于一个专门扎破气球的人,不断观察附近哪个气球没有被牵着,
发现了以后就把它扎破,释放内存空间
[解决办法]
我觉得不会有太大用处,毕竟垃圾回收是 .NET 自动进行的,想通过将引用设为 null 让对象立刻释放那是不可能的。在某些情形下加快释放倒有可能,比如说这个引用刚好是最后一个持有对象的引用,如果设为 null 后,刚好碰上回收,那对象就销毁了,否则回收器会认为对象仍然有引用而不进行回收。但作用应该有限,因为很多引用的生存期很短,设不设为 NULL 相差不大,长生存期的引用所指向的对象又多会有比较复杂的引用关系,这个引用是最后一个同时又遇上回收,这种机率也太小了吧。
至于析构函数,也是由垃圾回收器调用的,把引用置为 null 了,也不会立即给你调。而 Dispose 只是释放对象所拥有的一些资源,对象本身还是要等垃圾回收器来释放,总之,最终还是要看垃圾回收器的。
呵呵,个人理解,可能有误,敬请指正。

[解决办法]
看看Essential .NET,里面对于GC讲的很清楚。拜托大家不要凭感觉瞎猜,.NET出来快十年了,讲垃圾回收的文章遍地都是。看过后,你就知道,为什么要有这么一个不伦不类的析构函数、为什么会有FinalizeQueue、为什么对于非托管资源要人工Close或者Dispose。
[解决办法]
mark
很好,谢谢,学习!
[解决办法]
探讨
按我的理解,每个对象都是一个气球,当你要某一个气球的时候,就把它吹大,然后用一根绳子系着,同一个气球有可能被多个人同时牵着,
它还没破的时候就一直占用空间(内存),GC相当于一个专门扎破气球的人,不断观察附近哪个气球没有被牵着,
发现了以后就把它扎破,释放内存空间

[解决办法]
mark and up and study
[解决办法]
=nothing都不释放,
[解决办法]
很好!学习
[解决办法]
学习学习


[解决办法]
string sss=string.Empty; 释放吗
[解决办法]

探讨
string sss=string.Empty; 释放吗

[解决办法]
习惯上加上为好,可避免内存泄漏或溢出!!
[解决办法]
学习
[解决办法]
内存的申请和释放是C/C++的概念,C#已经没有这些概念了,也不用在析构函数中释放内存(我以前犯过这个错误),这些事都由框架来完成了。
[解决办法]
本人认为,加上=null是为了告诉JVM这个对象可以被回收,不然的话要过一段时间确定对象不再被使用了,才会回收,但是加快速度是相对的,并不存在立刻回收的说法,好像没见过所谓立即回收的实现方法
[解决办法]
up
[解决办法]
学习学习
[解决办法]
[size=12px][/size]
探讨
按我的理解,每个对象都是一个气球,当你要某一个气球的时候,就把它吹大,然后用一根绳子系着,同一个气球有可能被多个人同时牵着,
它还没破的时候就一直占用空间(内存),GC相当于一个专门扎破气球的人,不断观察附近哪个气球没有被牵着,
发现了以后就把它扎破,释放内存空间

[解决办法]
个人认为局部对象在离开方法以后就失去引用,这个时候,回收器会认为该对象可回收。
因此obj = null;这行代码在不太大的方法内,还是不用的好。
[解决办法]
学习学习
个人认为=null不能马上调用垃圾回收
应该可以提高点效率
因为在调用时是先把对象清空的
个人意见
[解决办法]
纠正一下,因该是作用域内
[解决办法]
好贴
收藏
[解决办法]
study
[解决办法]
探讨
up
个人觉得加不加=null没有什么影响,当然我没测试过,不能断言

[解决办法]
个人认为加上obj=null还是有用的。
[解决办法]
探讨
=null应该不释放,再加上GC.Collect()才能控制释放,否则就要等自动的垃圾回收了!

[解决办法]
用处不大
[解决办法]
楼上的,obj = null;目的就是为了让该对象的引用数为0(如果没在别的地方引用)
出了作用域obj的引用数也为0。
如果作用域内的代码很少,还不如不写。
[解决办法]
误伤
[解决办法]
郁闷积分不够
[解决办法]
标记下来看
[解决办法]
不大懂,但是好象刚学java时候书上看到GC是没办法自己来控制了
[解决办法]
我先去搬个凳子。等我
[解决办法]
学习
[解决办法]
framework在“内存”资源紧张时才会中断正在执行的代码去释放对象
楼主的代码是“连接池”资源用尽,framework不可能知道的
[解决办法]
ew jwetop optew[
------解决方案--------------------


收藏收藏~知道很多关于释放资源的资料~谢谢各位高手啦
[解决办法]
原来是在C#版,这个问题C#我不太清楚。
但是在jvm里面,ibm和sun都是虚拟机的实现。我以前在sun的官方文档里看过有关内存管理的文章的,上面讲到了一种垃圾回收的实现——jvm对每个对象都保存有一个引用数目(多少个引用指向这个内存地址),在第一次分配内存的时候会对这个引用数目加1,当这个引用不可见的时候就减1.引用数目为零的时候,就指明可垃圾回收了,但何时回收要看jvm的具体实现了。由此可见:在一部分情况下,con=null;就可以显式的让引用数目减1,对于加快垃圾回收还是有一点作用。

ibm的实现,我没有看相关的文章,不好说了。
[解决办法]
obj=null是肯定有用的。
不管它是不是能实时回收,
显式的断开引用只会让你的代码工作更加可靠,可读性更好。

可以看一下c的free函数,调用之后是否就真的释放的内存?
还是有可能成为dangling pointer?

看了这个帖子,
我还是没有想到.net的程序员果然还是比较“初级”。
难怪待遇不太容易提上去。

感觉.net是个很四不像的烂东西,
既然是虚拟机,CLR之类的东西,却又弄出析构函数和dispose...
还有什么unsafe的代码,靠,托管的就一定是safe的?
难怪微软的自己的.net设计师都对这个东西没信心。
[解决办法]
obj=null是肯定有用的。
不管它是不是能实时回收,
显式的断开引用只会让你的代码工作更加可靠,可读性更好。

可以看一下c的free函数,调用之后是否就真的释放的内存?
还是有可能成为dangling pointer?

看了这个帖子,
我还是没有想到.net的程序员果然还是比较“初级”。
难怪待遇不太容易提上去。

感觉.net是个很四不像的烂东西,
既然是虚拟机,CLR之类的东西,却又弄出析构函数和dispose...
还有什么unsafe的代码,靠,托管的就一定是safe的?
难怪微软的自己的.net设计师都对这个东西没信心。
[解决办法]
感觉obj=null 就是告诉程序 可以释放了 然后等着释放

说有多大用 还没感觉出来

但对程序的可读性还是很有帮助的
[解决办法]
mark
[解决办法]
mark
[解决办法]
学习
[解决办法]
回帖是一种美德!每天回帖即可获得 10 分可用分
[解决办法]
垃圾回收就是让程序员少操心,专注业务逻辑
大家反倒在这大操心,不是多此一举吗
=null不过是提前了10^-N纳秒断开了引用,这个在绝大多数系统中真的就那么重要?
当然一些特殊情况要特殊对待
[解决办法]
学习
[解决办法]
路过
[解决办法]

探讨
IBM照道理不测试C#.  应该研究的是Java. 不过二者的垃圾回收机制应该是极度相似的。

从理论上来说:垃圾回收器的进程优先级非常低,所以导致回收速度很慢。
有些高性能程序还是需要自己来释放内存/资源,而不能等垃圾回收器来回收。

[解决办法]
探讨
obj=null是肯定有用的。
不管它是不是能实时回收,
显式的断开引用只会让你的代码工作更加可靠,可读性更好。

可以看一下c的free函数,调用之后是否就真的释放的内存?
还是有可能成为dangling pointer?

看了这个帖子,
我还是没有想到.net的程序员果然还是比较“初级”。
难怪待遇不太容易提上去。

感觉.net是个很四不像的烂东西,
既然是虚拟机,CLR之类的东西,却又弄出析构函数和dispose...
还有什…

[解决办法]
Mark!
[解决办法]
又学习了……

热点排行