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()再断开对象与引用之间的关系。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值