弱引用研究

简介:

通常的,当说起对象引用的时候,一般指的是强引用,即只要这个对象还是可达状态(还会被程序访问到),那么垃圾回收器就不会去回收它。

而弱引用的对象被认为是不可达的,但它可以由应用程序访问,同时还能被垃圾回收器收回。支持垃圾收集的语言大多都支持弱引用,例如Java,C#,Python等。

通常,弱引用特别适合以下对象:占用大量内存,但通过垃圾回收功能回收以后很容易重新创建。C#中使用WeakReference类来创建弱引用对象。

下面是示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  string  FilePath =  "PathToMyImportantFile.dat" ;
        public  WeakReference WeakRef =  new  WeakReference( null );
        public  object  ImportantBigFileContents
        {
            get
            {
                object  bigObject = WeakRef.Target;
                if  (bigObject ==  null ) // 该弱引用已经被回收了,那么就变成null,则需要构造大对象。
                {
                    using  (StreamReader r =  new  StreamReader(FilePath))
                        bigObject = r.ReadToEnd();
                    WeakRef.Target = bigObject;
                }
                return  bigObject;
            }
        }

假设ImportantBigFileContents是某一个类的属性,该属性值是一个很占内存的对象,那么可以考虑使用弱引用存储这个大对象。

如果弱引用中的Target属性中的值仍然存在,则直接获取这个值返回。如果这个值已经被垃圾回收器回收掉了,那么这个值就是null。因此需要重新构造出该大对象。

注意,垃圾回收器究竟再何时启动,程序员是没法掌控的,因此也不能确定弱引用对象何时被回收。所以,很容易犯如下的错误,比如如下代码:

1
2
3
4
5
6
7
8
9
10
public  object  ImportantBigFileContents
        {
            get
            {
                if  (WeakRef.Target ==  null )
                    using  (StreamReader r =  new  StreamReader(FilePath))
                        WeakRef.Target = r.ReadToEnd();
                return  WeakRef.Target;
            }
        }

看上去没啥错误,如果WeakRef.Target属性为null则构造出大对象,如果WeakRef.Target有值则返回该值。

但是这里有一个小概率事情,由于垃圾回收器是异步执行的,你不会知道啥时回收,有一种可能是要调用return WeakRef.Target;句子前回收了。这样的话就会导致返回null。因此,推荐的做法是在读取弱引用对象之前,还是把它放入强引用对象中,即放入一个普通的对象中去。

弱引用还可以用来处理内存泄露的风险,例如常见的垃圾回收算法是引用计数,引用计数法计算了对象被引用的次数,在被引用的次数为0的时候,回收该对象。但是对于环形引用的对象,无法回收。即比如A中对象引用了B对象,B对象中也引用了A对象,这种情况下,垃圾回收器无法回收A对象和B对象,一旦这种环形引用的多了之后,就会引发内存泄露。

如果把A对象和B对象都设成弱引用的话,GC在必要的时候还是会收回资源的。

但是同时也要避免对小对象使用弱引用,因为指针本身可能和对象一样大,或者比对象还大。事实上,如果内存不是那么紧张的话,也没必要过度的使用弱引用。















本文转自cnn23711151CTO博客,原文链接: http://blog.51cto.com/cnn237111/1243849,如需转载请自行联系原作者

相关文章
|
10月前
|
Java 程序员
【JVM】强软弱虚引用详细解释
【JVM】强软弱虚引用详细解释
|
5月前
|
缓存 安全 Java
深入探索研究volatile
【10月更文挑战第16天】
36 7
|
9月前
|
程序员 C++
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
|
10月前
|
Java
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
【JVM】深入理解Java引用类型:强引用、软引用、弱引用和虚引用
583 0
|
10月前
|
存储 算法 安全
深入探究Java内存模型
深入探究Java内存模型
|
Java
JVM学习日志(八) 强引用,软引用,弱引用,虚引用
强引用,软引用,弱引用,虚引用 简述
138 0
JVM学习日志(八) 强引用,软引用,弱引用,虚引用
|
存储 缓存 Java
第二季:4.强引用、软引用、弱引用、虚引用分别是什么?【Java面试题】
第二季:4.强引用、软引用、弱引用、虚引用分别是什么?【Java面试题】
82 0
|
存储 编译器
第十二章-类和动态内存分配
第十二章-类和动态内存分配
113 0
|
算法 Java
二、垃圾回收算法与思想
主要的垃圾回收算法 一、引用计数器 引用计数器实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1。当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0。则对象A就不可能再被使用了。只要为每个对象配备一个整型的计数器即可。但是计数器有个一个严重的问题,即无法处理循环引用的情况。因此在java的垃圾回收器中,没有使用这个算法。
82 0
|
缓存 Java
弱引用该怎么用?
弱引用该怎么用?
138 0
弱引用该怎么用?