Java中没有指针的概念,而引用就是一个弱化的指针,保证开发不能任意操作内存。最近整理了一下之前不明白的各种级别引用:强引用、软引用、弱引用、虚引用,它们的特点和应用场景汇总如下:
1、强引用
如果一个对象具有强引用,GC绝不会回收它;当内存空间不足,JVM宁愿抛出OutOfMemoryError错误。一般new出来的对象都是强引用,如下
<code class="hljs cs has-numbering"><span class="hljs-comment">//强引用 </span> User strangeReference=<span class="hljs-keyword">new</span> User(); </code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>
2、软引用
如果一个对象具有软引用,当内存空间不足,GC会回收这些对象的内存,使用软引用构建敏感数据的缓存。
在JVM中,软引用是如下定义的,可以通过一个时间戳来回收,下面引自JVM:
<code class="hljs scala has-numbering"> public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SoftReference</span><<span class="hljs-title">T</span>> <span class="hljs-keyword">extends</span> <span class="hljs-title">Reference</span><<span class="hljs-title">T</span>> {</span> <span class="hljs-javadoc">/** * Timestamp clock, updated by the garbage collector */</span> static <span class="hljs-keyword">private</span> long clock; <span class="hljs-javadoc">/** * 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. */</span> <span class="hljs-keyword">private</span> long timestamp; <span class="hljs-javadoc">/** * Creates a new soft reference that refers to the given object. The new * reference is not registered with any queue. * * <span class="hljs-javadoctag">@param</span> referent object the new soft reference will refer to */</span> public SoftReference(T referent) { <span class="hljs-keyword">super</span>(referent); <span class="hljs-keyword">this</span>.timestamp = clock; } <span class="hljs-javadoc">/** * Creates a new soft reference that refers to the given object and is * registered with the given queue. * * <span class="hljs-javadoctag">@param</span> referent object the new soft reference will refer to * <span class="hljs-javadoctag">@param</span> q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required * */</span> public SoftReference(T referent, ReferenceQueue<? <span class="hljs-keyword">super</span> T> q) { <span class="hljs-keyword">super</span>(referent, q); <span class="hljs-keyword">this</span>.timestamp = clock; } <span class="hljs-javadoc">/** * 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>. * * <span class="hljs-javadoctag">@return</span> The object to which this reference refers, or * <code>null</code> if this reference object has been cleared */</span> public T get() { T o = <span class="hljs-keyword">super</span>.get(); <span class="hljs-keyword">if</span> (o != <span class="hljs-keyword">null</span> && <span class="hljs-keyword">this</span>.timestamp != clock) <span class="hljs-keyword">this</span>.timestamp = clock; <span class="hljs-keyword">return</span> o; } } </code>
软引用的声明的借助强引用或者匿名对象,使用泛型SoftReference;可以通过get方法获得强引用。具体如下:
<code class="hljs cs has-numbering"><span class="hljs-comment">//软引用</span> SoftReference<User>softReference=<span class="hljs-keyword">new</span> SoftReference<User>(<span class="hljs-keyword">new</span> User()); strangeReference=softReference.<span class="hljs-keyword">get</span>();<span class="hljs-comment">//通过get方法获得强引用</span></code>
3、弱引用
如果一个对象具有弱引用,在GC线程扫描内存区域的过程中,不管当前内存空间足够与否,都会回收内存,使用弱引用 构建非敏感数据的缓存。
在JVM中,弱引用是如下定义的,下面引自JVM:
<code class="hljs scala has-numbering">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeakReference</span><<span class="hljs-title">T</span>> <span class="hljs-keyword">extends</span> <span class="hljs-title">Reference</span><<span class="hljs-title">T</span>> {</span> <span class="hljs-javadoc">/** * Creates a new weak reference that refers to the given object. The new * reference is not registered with any queue. * * <span class="hljs-javadoctag">@param</span> referent object the new weak reference will refer to */</span> public WeakReference(T referent) { <span class="hljs-keyword">super</span>(referent); } <span class="hljs-javadoc">/** * Creates a new weak reference that refers to the given object and is * registered with the given queue. * * <span class="hljs-javadoctag">@param</span> referent object the new weak reference will refer to * <span class="hljs-javadoctag">@param</span> q the queue with which the reference is to be registered, * or <tt>null</tt> if registration is not required */</span> public WeakReference(T referent, ReferenceQueue<? <span class="hljs-keyword">super</span> T> q) { <span class="hljs-keyword">super</span>(referent, q); } }</code>
弱引用的声明的借助强引用或者匿名对象,使用泛型WeakReference<T>,具体如下:
<code class="hljs cs has-numbering"><span class="hljs-comment">//弱引用</span> WeakReference<User>weakReference=<span class="hljs-keyword">new</span> WeakReference<User>(<span class="hljs-keyword">new</span> User());</code>
4、虚引用
如果一个对象仅持有虚引用,在任何时候都可能被垃圾回收,虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列联合使用,虚引用主要用来跟踪对象 被垃圾回收的活动。
在JVM中,虚引用是如下定义的,下面引自JVM:
<code class="hljs applescript has-numbering"> public <span class="hljs-type">class</span> PhantomReference<T> extends Reference<T> { /** * Returns this <span class="hljs-keyword">reference</span> object's referent. Because <span class="hljs-keyword">the</span> referent <span class="hljs-keyword">of</span> a * phantom <span class="hljs-keyword">reference</span> <span class="hljs-keyword">is</span> always inaccessible, this method always returns * <code>null</code>. * * @<span class="hljs-constant">return</span> <code>null</code> */ public T <span class="hljs-keyword">get</span>() { <span class="hljs-command"> return</span> null; } /** * Creates a new phantom <span class="hljs-keyword">reference</span> <span class="hljs-keyword">that</span> refers <span class="hljs-keyword">to</span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">given</span> object <span class="hljs-keyword">and</span> * <span class="hljs-keyword">is</span> registered <span class="hljs-keyword">with</span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">given</span> queue. * * <p> It <span class="hljs-keyword">is</span> possible <span class="hljs-keyword">to</span> create a phantom <span class="hljs-keyword">reference</span> <span class="hljs-keyword">with</span> a <tt>null</tt> * queue, <span class="hljs-keyword">but</span> such <span class="hljs-keyword">a reference</span> <span class="hljs-keyword">is</span> completely useless: Its <tt><span class="hljs-keyword">get</span></tt> * method will always <span class="hljs-constant">return</span> null <span class="hljs-keyword">and</span>, <span class="hljs-keyword">since</span> <span class="hljs-keyword">it</span> <span class="hljs-keyword">does</span> <span class="hljs-keyword">not</span> have a queue, <span class="hljs-keyword">it</span> * will never be enqueued. * * @param referent <span class="hljs-keyword">the</span> object <span class="hljs-keyword">the</span> new phantom <span class="hljs-keyword">reference</span> will refer <span class="hljs-keyword">to</span> * @param q <span class="hljs-keyword">the</span> queue <span class="hljs-keyword">with</span> which <span class="hljs-keyword">the</span> <span class="hljs-keyword">reference</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">to</span> be registered, * <span class="hljs-keyword">or</span> <tt>null</tt> <span class="hljs-keyword">if</span> registration <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> required */ public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }</code>
虚引用PhantomReference<T>的声明的借助强引用或者匿名对象,结合泛型ReferenceQueue<T>初始化,具体如下:
<code class="hljs cs has-numbering"><span class="hljs-comment">//虚引用</span> PhantomReference<User> phantomReference=<span class="hljs-keyword">new</span> PhantomReference<User>(<span class="hljs-keyword">new</span> User(),<span class="hljs-keyword">new</span> ReferenceQueue<User>());</code>
5、总结
下面是一段关于强引用、软引用、弱引用、虚引用的程序:
<code class="hljs cs has-numbering">import java.lang.<span class="hljs-keyword">ref</span>.*; import java.util.HashSet; import java.util.Set; class User { <span class="hljs-keyword">private</span> String name; <span class="hljs-keyword">public</span> <span class="hljs-title">User</span>() {} <span class="hljs-keyword">public</span> <span class="hljs-title">User</span>(String name) { <span class="hljs-keyword">this</span>.name=name; } @Override <span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span>() { <span class="hljs-keyword">return</span> name; } <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span>(){ System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Finalizing ... "</span>+name); } } <span class="hljs-comment">/** * Created by jinxu on 15-4-25. */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> ReferenceDemo { <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ReferenceQueue<User> referenceQueue = <span class="hljs-keyword">new</span> ReferenceQueue<User>(); <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> final <span class="hljs-keyword">int</span> size = <span class="hljs-number">10</span>; <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">checkQueue</span>(){ <span class="hljs-comment">/* Reference<? extends User> reference = null; while((reference = referenceQueue.poll())!=null){ System.out.println("In queue : "+reference.get()); }*/</span> Reference<? extends User> reference = referenceQueue.poll(); <span class="hljs-keyword">if</span>(reference!=<span class="hljs-keyword">null</span>){ System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"In queue : "</span>+reference.<span class="hljs-keyword">get</span>()); } } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSoftReference</span>() { Set<SoftReference<User>> softReferenceSet = <span class="hljs-keyword">new</span> HashSet<SoftReference<User>>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) { SoftReference<User> <span class="hljs-keyword">ref</span> = <span class="hljs-keyword">new</span> SoftReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Soft "</span> + i), referenceQueue); System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>()); softReferenceSet.add(<span class="hljs-keyword">ref</span>); } System.gc(); checkQueue(); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testWeaKReference</span>() { Set<WeakReference<User>> weakReferenceSet = <span class="hljs-keyword">new</span> HashSet<WeakReference<User>>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) { WeakReference<User> <span class="hljs-keyword">ref</span> = <span class="hljs-keyword">new</span> WeakReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Weak "</span> + i), referenceQueue); System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>()); weakReferenceSet.add(<span class="hljs-keyword">ref</span>); } System.gc(); checkQueue(); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testPhantomReference</span>() { Set<PhantomReference<User>> phantomReferenceSet = <span class="hljs-keyword">new</span> HashSet<PhantomReference<User>>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < size; i++) { PhantomReference<User> <span class="hljs-keyword">ref</span> = <span class="hljs-keyword">new</span> PhantomReference<User>(<span class="hljs-keyword">new</span> User(<span class="hljs-string">"Phantom "</span> + i), referenceQueue); System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Just created: "</span> + <span class="hljs-keyword">ref</span>.<span class="hljs-keyword">get</span>()); phantomReferenceSet.add(<span class="hljs-keyword">ref</span>); } System.gc(); checkQueue(); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) { testSoftReference(); testWeaKReference(); testPhantomReference(); } }</code>
结果为
<code class="hljs r has-numbering">Just created: Soft <span class="hljs-number">0</span> Just created: Soft <span class="hljs-number">1</span> Just created: Soft <span class="hljs-number">2</span> Just created: Soft <span class="hljs-number">3</span> Just created: Soft <span class="hljs-number">4</span> Just created: Soft <span class="hljs-number">5</span> Just created: Soft <span class="hljs-number">6</span> Just created: Soft <span class="hljs-number">7</span> Just created: Soft <span class="hljs-number">8</span> Just created: Soft <span class="hljs-number">9</span> Just created: Weak <span class="hljs-number">0</span> Just created: Weak <span class="hljs-number">1</span> Just created: Weak <span class="hljs-number">2</span> Just created: Weak <span class="hljs-number">3</span> Just created: Weak <span class="hljs-number">4</span> Just created: Weak <span class="hljs-number">5</span> Just created: Weak <span class="hljs-number">6</span> Just created: Weak <span class="hljs-number">7</span> Just created: Weak <span class="hljs-number">8</span> Just created: Weak <span class="hljs-number">9</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">7</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">8</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">9</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">4</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">5</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">6</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">0</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">1</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">2</span> Finalizing <span class="hljs-keyword">...</span> Weak <span class="hljs-number">3</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">9</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">8</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">7</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">6</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">5</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">4</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">3</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">2</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">1</span> Finalizing <span class="hljs-keyword">...</span> Soft <span class="hljs-number">0</span> 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 <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">9</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">7</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">8</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">4</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">5</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">6</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">0</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">1</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">2</span> Finalizing <span class="hljs-keyword">...</span> Phantom <span class="hljs-number">3</span> </code>
转自:http://blog.youkuaiyun.com/xiaofengcanyuexj/article/details/45271195