Java强引用、软引用、弱引用、虚引用详解
***********************************************声明******************************************************
原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。
由于各种原因,可能存在诸多不足,欢迎斧正!
*********************************************************************************************************Java中没有指针的概念,而引用就是一个弱化的指针,保证开发不能任意操作内存。最近整理了一下之前不明白的各种级别引用:强引用、软引用、弱引用、虚引用,它们的特点和应用场景汇总如下:
1、强引用
如果一个对象具有强引用,GC绝不会回收它;当内存空间不足,JVM宁愿抛出OutOfMemoryError错误。一般new出来的对象都是强引用,如下
//强引用 User strangeReference=new User();
2、软引用
如果一个对象具有软引用,当内存空间不足,GC会回收这些对象的内存,使用软引用构建敏感数据的缓存。
在JVM中,软引用是如下定义的,可以通过一个时间戳来回收,下面引自JVM:
public class SoftReference<T> extends Reference<T> { /** * Timestamp clock, updated by the garbage collector */ static private long clock; /** * Timestamp updated by each invocation of the get method. The VM may use * this field when selecting soft references to be cleared, but it is not * required to do so. */ private long timestamp; /** * Creates a new soft reference that refers to the given object. The new * reference is not registered with any queue. * * @param referent object the new soft reference will refer to */ public SoftReference(T referent) { super(referent); this.timestamp = clock; } /** * Creates a new soft reference that refers to the given object and is * registered with the given queue. * * @param referent object the new soft reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required * */ public SoftReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); this.timestamp = clock; } /** * Returns this reference object's referent. If this reference object has * been cleared, either by the program or by the garbage collector, then * this method returns <code>null</code>. * * @return The object to which this reference refers, or * <code>null</code> if this reference object has been cleared */ public T get() { T o = super.get(); if (o != null && this.timestamp != clock) this.timestamp = clock; return o; } }软引用的声明的借助强引用或者匿名对象,使用泛型SoftReference<T>;可以通过get方法获得强引用。具体如下:
//软引用 SoftReference<User>softReference=new SoftReference<User>(new User()); strangeReference=softReference.get();//通过get方法获得强引用
3、弱引用
如果一个对象具有弱引用,在GC线程扫描内存区域的过程中,不管当前内存空间足够与否,都会回收内存,使用弱引用 构建非敏感数据的缓存。
在JVM中,弱引用是如下定义的,下面引自JVM:
public class WeakReference<T> extends Reference<T> { /** * Creates a new weak reference that refers to the given object. The new * reference is not registered with any queue. * * @param referent object the new weak reference will refer to */ public WeakReference(T referent) { super(referent); } /** * Creates a new weak reference that refers to the given object and is * registered with the given queue. * * @param referent object the new weak reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required */ public WeakReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }
弱引用的声明的借助强引用或者匿名对象,使用泛型WeakReference<T>,具体如下:
//弱引用 WeakReference<User>weakReference=new WeakReference<User>(new User());
4、虚引用
如果一个对象仅持有虚引用,在任何时候都可能被垃圾回收,虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列联合使用,虚引用主要用来跟踪对象 被垃圾回收的活动。
在JVM中,虚引用是如下定义的,下面引自JVM:
public class PhantomReference<T> extends Reference<T> { /** * Returns this reference object's referent. Because the referent of a * phantom reference is always inaccessible, this method always returns * <code>null</code>. * * @return <code>null</code> */ public T get() { return null; } /** * Creates a new phantom reference that refers to the given object and * is registered with the given queue. * * <p> It is possible to create a phantom reference with a <tt>null</tt> * queue, but such a reference is completely useless: Its <tt>get</tt> * method will always return null and, since it does not have a queue, it * will never be enqueued. * * @param referent the object the new phantom reference will refer to * @param q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required */ public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }虚引用PhantomReference<T>的声明的借助强引用或者匿名对象,结合泛型ReferenceQueue<T>初始化,具体如下:
//虚引用 PhantomReference<User> phantomReference=new PhantomReference<User>(new User(),new ReferenceQueue<User>());
5、总结
下面是一段关于强引用、软引用、弱引用、虚引用的程序:
import java.lang.ref.*; import java.util.HashSet; import java.util.Set; class User { private String name; public User() {} public User(String name) { this.name=name; } @Override public String toString() { return name; } public void finalize(){ System.out.println("Finalizing ... "+name); } } /** * Created by jinxu on 15-4-25. */ public class ReferenceDemo { private static ReferenceQueue<User> referenceQueue = new ReferenceQueue<User>(); private static final int size = 10; public static void checkQueue(){ /* Reference<? extends User> reference = null; while((reference = referenceQueue.poll())!=null){ System.out.println("In queue : "+reference.get()); }*/ Reference<? extends User> reference = referenceQueue.poll(); if(reference!=null){ System.out.println("In queue : "+reference.get()); } } public static void testSoftReference() { Set<SoftReference<User>> softReferenceSet = new HashSet<SoftReference<User>>(); for (int i = 0; i < size; i++) { SoftReference<User> ref = new SoftReference<User>(new User("Soft " + i), referenceQueue); System.out.println("Just created: " + ref.get()); softReferenceSet.add(ref); } System.gc(); checkQueue(); } public static void testWeaKReference() { Set<WeakReference<User>> weakReferenceSet = new HashSet<WeakReference<User>>(); for (int i = 0; i < size; i++) { WeakReference<User> ref = new WeakReference<User>(new User("Weak " + i), referenceQueue); System.out.println("Just created: " + ref.get()); weakReferenceSet.add(ref); } System.gc(); checkQueue(); } public static void testPhantomReference() { Set<PhantomReference<User>> phantomReferenceSet = new HashSet<PhantomReference<User>>(); for (int i = 0; i < size; i++) { PhantomReference<User> ref = new PhantomReference<User>(new User("Phantom " + i), referenceQueue); System.out.println("Just created: " + ref.get()); phantomReferenceSet.add(ref); } System.gc(); checkQueue(); } public static void main(String[] args) { testSoftReference(); testWeaKReference(); testPhantomReference(); } }
结果为
Just created: Soft 0 Just created: Soft 1 Just created: Soft 2 Just created: Soft 3 Just created: Soft 4 Just created: Soft 5 Just created: Soft 6 Just created: Soft 7 Just created: Soft 8 Just created: Soft 9 Just created: Weak 0 Just created: Weak 1 Just created: Weak 2 Just created: Weak 3 Just created: Weak 4 Just created: Weak 5 Just created: Weak 6 Just created: Weak 7 Just created: Weak 8 Just created: Weak 9 Finalizing ... Weak 7 Finalizing ... Weak 8 Finalizing ... Weak 9 Finalizing ... Weak 4 Finalizing ... Weak 5 Finalizing ... Weak 6 Finalizing ... Weak 0 Finalizing ... Weak 1 Finalizing ... Weak 2 Finalizing ... Weak 3 Finalizing ... Soft 9 Finalizing ... Soft 8 Finalizing ... Soft 7 Finalizing ... Soft 6 Finalizing ... Soft 5 Finalizing ... Soft 4 Finalizing ... Soft 3 Finalizing ... Soft 2 Finalizing ... Soft 1 Finalizing ... Soft 0 In queue : null Just created: null Just created: null Just created: null Just created: null Just created: null Just created: null Just created: null Just created: null Just created: null Just created: null In queue : null Finalizing ... Phantom 9 Finalizing ... Phantom 7 Finalizing ... Phantom 8 Finalizing ... Phantom 4 Finalizing ... Phantom 5 Finalizing ... Phantom 6 Finalizing ... Phantom 0 Finalizing ... Phantom 1 Finalizing ... Phantom 2 Finalizing ... Phantom 3
从程序运行结果可以看出,虚引用形同虚设,它所引用的对象随时可能被垃圾回收器回收,具有弱引用的对象拥有稍微长一点的生命周期,当垃圾回收器执行回收操作时,有可能被垃圾回收器回收,具有软引用的对象拥有更长的生命周期,但在Java虚拟机认为内存不足的情况下,也是会被垃圾回收器回收的。
由于时间有限,在写博文的过程中参考过一些文献,在此表示感谢;同时鉴于水平原因,你难免有不足之处,欢迎斧正!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。