四种引用

JVM

无论是通过引用计数算法判断对象的引用的数量,还是通过可达性分析算法判断对象的引用链是否可达,判断对象是否存活都跟“引用”有关。

从JDK 1.2后,java中的引用一共分为四种(引用强度依次减弱):

  • 强引用
  • 软引用
  • 弱引用
  • 虚引用

强引用

强引用就是直接的对象引用,类似 Object object = new Object();这类的引用,只要强引用还存在,垃圾回收器就永远不会回收掉被引用的对象。

软引用

描述一些还有用,但并非必须的对象。对于软引用引用的对象,在系统将要发生内存溢出之前,会对这些对象进行垃圾回收,如果回收后内存空间仍然不够,才会抛出内存溢出的异常。java提供了SoftReference来实现软引用。

弱引用

用来描述非必须的对象的,但是引用的强度要比软引用弱一点,被弱引用引用的对象,只要一发生垃圾回收,就会被回收掉。java提供了WeakReference类来描述弱引用。

虚引用

是最弱的一种引用关系。虚引用不会影响对象的生存时间,也无法通过虚引用获得对象的实例,虚引用跟没引用一样。使用虚引用的唯一的目的,就是能在对象被回收前收到一个系统的通知,虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用必须跟引用队列一起使用,当虚引用所引用的对象被回收掉后,虚引用将被添加到引用队列里面,java提供了PhantomReference类来实现虚引用。

上面的四种引用除了虚引用之外,都提供了一个get方法,用于获取被他们所引用的对象。使用这些引用类,可以避免在程序执行期间将对象留在内存中。如果以弱,软,虚方式引用对象,那么垃圾收集器就能够随意的释放对象。如果希望尽可能的减少程序在生命周期中所占用的内存,这些类很有用处。

由于垃圾回收的不确定性,当程序希望从软,弱引用中取出被引用的对象的时候,可能这个引用的对象已经被垃圾回收器回收掉了。如果程序希望使用那个被引用的对象,则必须重新创建这个对象。这个过程可以使用一下两种风格的代码来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//取出弱引用引用的对象
obj = wr.get();

if(obj==null){
//重新创建一个新的对象,再次让弱引用去引用该对象
wr = new WeakReference(recreateIt()); // 1
//取出所引用的对象,赋值给obj
obj = wr.get(); // 2
}

......//操作obj对象

//再次切断obj跟对象之间的联系
obj=null;

1
2
3
4
5
6
7
8
9
10
11
12
13
//取出弱引用引用的对象
obj = wr.get();

if(obj==null){
//重新创建一个新的对象,并使用强引用引用他
obj = recreateIt();
//取出弱引用所引用的对象,并将它赋值给obj变量
wr = new WeakReference(obj);
}
......//操作obj对象

//再次切断obj跟对象之间的联系
obj=null;

上述的第一种方式可能存在一些问题:当if语句执行完以后,obj可能还是为空,这是由于不垃圾回收的不确定性,假设系统在1,2间进行垃圾回收,则系统再次将wr引用的对象回收,obj依然是null。第二种方式则不存在问题。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器