.net的弱引用是什么?弱引用看起来很神奇,似乎是凌驾于正常的垃圾回收机制之上的,它究竟是如何实现的呢?其实WeakReference类型在内部封装了一个名为GCHandle的struct类型,正是这个GCHandle使弱引用成为可能。下面西安达内科技(www.xatarena.cn)培训讲师就详细为大家介绍。
CLR中的每个AppDomain都拥有一个GC句柄表。这个表的每一项记录有两个信息,一个是指向堆中某个对象的指针,另一个是这个表项的类型。总共有4种表项类型,其中Weak和WeakTrackResurrection两种类型和我们今天所讨论的弱引用相关。GCHandle这个类提供了一些操纵GC句柄表的方法。我们可以使用它的Alloc方法向GC句柄表中添加一个指定类型的表项。当垃圾回收开始后,垃圾回收器找到所有可达对象(简单的说,就是有用的对象)。然后遍历GC句柄表中每个Weak类型的表项,如果发现某表项所指的对象不属于可达对象,则会把该表项的对象指针设置为null。紧接着,垃圾回收器会找出所有不可达对象中定义了析构函数的对象,并把他们放到一个被称为freachable的队列中(freachable中的对象会等待一个CLR中特定的线程来调用他们的终结函数)。由于这些freachable中的对象现在又被freachable队列所引用,所以它们又成为可达对象了。此时,垃圾回收器会遍历GC句柄表中所有WeakTrackResurrection类型的表项,和刚才一样,如果某表项所指的对象不属于可达对象,则会把该表项的对象指针设置为null。此处需注意,对于那些一开始被判定为不可达且定义了析构函数的对象来说,它们在GC句柄表中所对于的表项指针仍然不是null。这就是Weak和WeakTrackResurrection两种类型的区别。
WeakReference就是通过表示了某个GC句柄表表项的GCHandle对象来完成跟踪对象生命周期的功能的。你也一定可以看出短弱引用利用了Weak类型的GC句柄表项,而长弱引用则利用了WeakTrackResurrection类型的表项。
WeakReference的一些注意事项
首先,WeakReference自身也实现了析构函数。也就是说,它即使不再被使用了,也不会被立即回收,而是会在内存里赖着多活一会(可能会经历不止一次的垃圾回收)。
另外,如上一节所说,WeakReference会向GC句柄表添加一个表项。而每次垃圾回收,GC句柄表都会被遍历一遍。可想而知,如果系统中存在大量的WeakReference,那么GC句柄表很可能也会非常庞大,导致垃圾回收的效率降低。 |
![](http://img.qy6.com.cn/images/noimg.gif) |
|