WeakReference(弱引用)让GC需要时回收对象
程序员文章站
2024-03-04 22:32:18
我们平常用的都是对象的强引用,如果有强引用存在,gc是不会回收对象的。我们能不能同时保持对对象的引用,而又可以让gc需要的时候回收这个对象呢?.net中提供了weakref...
我们平常用的都是对象的强引用,如果有强引用存在,gc是不会回收对象的。我们能不能同时保持对对象的引用,而又可以让gc需要的时候回收这个对象呢?.net中提供了weakreference来实现。弱引用可以让您保持对对象的引用,同时允许gc在必要时释放对象,回收内存。对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望gc必要时回收时,可以考虑使用弱引用。弱引用使用起来很简单,看下面的代码:
object obj = new object();
weakreference wref = new weakreference( obj );
obj = null;
第一行代码新建了一个新的对象,这里叫它对象a,obj是对对象a的强引用。接着第二行代码新建了一个弱引用对象,参数就是对象a的强引用,第三行代码释放掉对对象a的强引用。这时如果gc进行回收,对象a就会被回收。
怎样在取得对象a的强引用呢?很简单,请看代码2:
object obj2 = wref.target;
if( obj2 != null )
{
// 做你想做的事吧。
}
else
{
// 对象已经被回收,如果要用必须新建一个。
}
只要显示的将弱引用的target属性附值就会得到弱引用所代表对象的一个强引用。不过在使用对象之前要对其可用性进行检查,因为它可能已经被回收了。如 果你得到的是null(vb.net下为nothing),表明对象已经被回收,不能再用了,需要重新分配一个。如果不是null,就可以放心大胆的用 了。
接下来让我们看weakreference的另外一个版本,请看代码3:
// public weakreference(
// object target,
// bool trackresurrection
//);
object obj1 = new object();
object obj2 = new object();
weakreference wref1 = new weakreference( obj1, false );
weakreference wref2 = new weakreference( obj2, true );
weakreference的另外一个版本有两个参数,第一个参数和我们前面用的版本的一样。第二个参数让我们看一下他的原型,bool trackresurrection,跟踪复活,是个bool型,就是是否跟踪复活。前面的文章中我提到过需要finalize的对象在最终释放前会有一 次复活,我们大概可以猜到第二个参数表示的意思了。如果我们第二个参数给false,这个弱引用就是一个short weak reference(短弱引用),当gc回收时,发现根中没有这个对象的引用了,就认为这个对象无用,这时短弱引用对这个对象的跟踪到此为止,弱引用的 target被设置为null。前面的一个参数的构造函数版本新建的弱引用为短弱引用。如果第二个参数给true,这个弱引用就是一个long weak reference(长弱引用)。在对象的finalize方法没有被执行以前,target都可用。不过这是对象的某些成员变量也许已经被回收,所以使 用起来要想当小心。
现在让我们看看weakreference是如何实现的。很显然weakreference不能直接的引用目标对象,weakreference的 target属性的get/set是两个函数,从某处查到目标对象的引用返回,而不是我们最常用写的那样直接返回或者设置一个私有变量。gc维护了两个列 表来跟踪两种弱引用的目标对象,在一个 weakreference对象创建时,它在相应的列表中找到一个位置,将目标对象的引用放入,很显然,这两个列表不是根的一部分。在gc进行内存回收的 时候,如果要回收某一个对象,会检查弱引用的列表,如果保存着这个对象的引用,则将其设为null。
public class asppage : page
{
private static arraylist __enclist = new arraylist();
[debuggernonusercode]
public asppage()
{
base.load += new eventhandler(this.page_load);
arraylist list = __enclist;
lock (list)
{
__enclist.add(new weakreference(this));
}
}
}
复制代码 代码如下:
object obj = new object();
weakreference wref = new weakreference( obj );
obj = null;
第一行代码新建了一个新的对象,这里叫它对象a,obj是对对象a的强引用。接着第二行代码新建了一个弱引用对象,参数就是对象a的强引用,第三行代码释放掉对对象a的强引用。这时如果gc进行回收,对象a就会被回收。
怎样在取得对象a的强引用呢?很简单,请看代码2:
复制代码 代码如下:
object obj2 = wref.target;
if( obj2 != null )
{
// 做你想做的事吧。
}
else
{
// 对象已经被回收,如果要用必须新建一个。
}
只要显示的将弱引用的target属性附值就会得到弱引用所代表对象的一个强引用。不过在使用对象之前要对其可用性进行检查,因为它可能已经被回收了。如 果你得到的是null(vb.net下为nothing),表明对象已经被回收,不能再用了,需要重新分配一个。如果不是null,就可以放心大胆的用 了。
接下来让我们看weakreference的另外一个版本,请看代码3:
复制代码 代码如下:
// public weakreference(
// object target,
// bool trackresurrection
//);
object obj1 = new object();
object obj2 = new object();
weakreference wref1 = new weakreference( obj1, false );
weakreference wref2 = new weakreference( obj2, true );
weakreference的另外一个版本有两个参数,第一个参数和我们前面用的版本的一样。第二个参数让我们看一下他的原型,bool trackresurrection,跟踪复活,是个bool型,就是是否跟踪复活。前面的文章中我提到过需要finalize的对象在最终释放前会有一 次复活,我们大概可以猜到第二个参数表示的意思了。如果我们第二个参数给false,这个弱引用就是一个short weak reference(短弱引用),当gc回收时,发现根中没有这个对象的引用了,就认为这个对象无用,这时短弱引用对这个对象的跟踪到此为止,弱引用的 target被设置为null。前面的一个参数的构造函数版本新建的弱引用为短弱引用。如果第二个参数给true,这个弱引用就是一个long weak reference(长弱引用)。在对象的finalize方法没有被执行以前,target都可用。不过这是对象的某些成员变量也许已经被回收,所以使 用起来要想当小心。
现在让我们看看weakreference是如何实现的。很显然weakreference不能直接的引用目标对象,weakreference的 target属性的get/set是两个函数,从某处查到目标对象的引用返回,而不是我们最常用写的那样直接返回或者设置一个私有变量。gc维护了两个列 表来跟踪两种弱引用的目标对象,在一个 weakreference对象创建时,它在相应的列表中找到一个位置,将目标对象的引用放入,很显然,这两个列表不是根的一部分。在gc进行内存回收的 时候,如果要回收某一个对象,会检查弱引用的列表,如果保存着这个对象的引用,则将其设为null。
复制代码 代码如下:
public class asppage : page
{
private static arraylist __enclist = new arraylist();
[debuggernonusercode]
public asppage()
{
base.load += new eventhandler(this.page_load);
arraylist list = __enclist;
lock (list)
{
__enclist.add(new weakreference(this));
}
}
}
上一篇: asp.net 实现下拉框只读功能