标签:
Java存在着几种引用:强引用,SoftReference,WeakReference和PhantomRefrence。可以简单的称为:强、软、弱、虚。引用的强度是依次递减的。
强引用意味着对象还要被使用,是不可以被回收的。
软引用可以被回收,但回收的时机是引用对象不再存在强引用指向它,并且JVM内存不足时。
弱引用可以被回收,它不影响GC,对象按照正常的回收机制进行回收。在对象未被回收时,可以继续使用。因此,软引用的使用需要null检查。
虚引用可以被回收,它不影响GC。虚引用的对象get不到,也就是说虚引用的对象不能再使用。虚引用主要用来准备知道对象被GC的时机。
结合各种引用的特性,可以发现SoftReference比较适合做缓存,因为它可以驻留内存,但是又不会导致OOM。WeakReference适用的时机是不想影响对象的正常回收的时候,比如容器存储。PhantomRefrence的很少使用。PhantomRefrence的一个用处是解决Java析构函数finilze的误用(覆盖finilze并创建新的强引用),因为PhantomRefrence是在执行finilze之后进行回收的。
SoftReference,WeakReference和PhantomRefrence都可以接受一个ReferenceQueue<T>参数。当它们引用的对象被回收时,引用对象会被放置到ReferenceQueue<T>中。
看一个示例,对三种引用就有一个比较好的认识了。
public class RefTest { public static void main(String args[]){ String s1 = new String("abc"); String s2 = new String("def"); String s3 = new String("hij"); ReferenceQueue<String> srq = new ReferenceQueue<String>(); SoftReference<String> ss = new SoftReference<String>(s1, srq); ReferenceQueue<String> wrq = new ReferenceQueue<String>(); WeakReference<String> ws = new WeakReference<String>(s2, wrq); ReferenceQueue<String> prq = new ReferenceQueue<String>(); PhantomReference<String> ps = new PhantomReference<String>(s3, prq); System.out.println("ps = " + ps.get()); s1 = null; s2 = null; s3 = null; System.gc(); System.out.println("ss = " + ss.get()); System.out.println("srq = " + srq.poll()); System.out.println("ws = " + ws.get()); System.out.println("srq = " + wrq.poll()); System.out.println("ps = " + ps.get()); System.out.println("prq = " + prq.poll()); } }
16行使用虚引用来获取对象,这是不可行的。得到的对象是null。
18-20行释放三个字符对象上的强引用。
22行尝试做一次GC,会释放s2和s3。s1还存在软引用,内存也还充分,所以不会被回收。
24-25行尝试使用软引用,这时还是有效的,所以对应的ReferenceQueue为空。
26-27行尝试使用弱引用,因为s2的强引用已经释放,弱引用已经失效,对应的ReferenceQueue放置的是已经失效的弱引用。
28-29行尝试使用虚引用,因为s3的强引用已经释放,弱引用已经失效(即使强引用还在,也失效),对应的ReferenceQueue放置的是已经失效的虚引用。
最后的输出:
ps = null ss = abc srq = null ws = null wrq = java.lang.ref.WeakReference@13bad12 ps = null prq = java.lang.ref.PhantomReference@df8ff1
标签:
原文地址:http://my.oschina.net/sulliy/blog/482101