本文將談一下對SoftReference(軟引用)、WeakReference(弱引用)和PhantomRefrence(虛引用)的理解三各類理解,這三個(gè)類是對heap中java對象的應(yīng)用,通過這個(gè)三個(gè)類可以和gc做簡單的交互.
引用種類
除了上面提到的三個(gè)引用之外,還有一個(gè)引用,也就是最長用到的那就是強(qiáng)引用.例如
Object o=new Object();Object o1=o;
上面代碼中第一句是在heap堆中創(chuàng)建新的Object對象通過o引用這個(gè)對象,第二句是通過o建立o1到new Object()這個(gè)heap堆中的對象的引用,這兩個(gè)引用都是強(qiáng)引用.只要存在對heap中對象的引用,gc就不會(huì)收集該對象.如果通過如下代碼
o=null;o1=null;
顯示的設(shè)置o和o1為null,或超出范圍,則gc認(rèn)為該對象不存在引用,就可以搜集它了.可以收集,并不等于就一會(huì)被收集.什么時(shí)候收集這要取決于gc的算法.這要就帶來很對不一定性.例如你就想指定一個(gè)對象,希望下次gc運(yùn)行時(shí)把它收集了,那就沒辦法了,有了其他的三種引用就可以做到了。其他的三種引用在不妨礙gc收集的情況下,可以做簡單的交互.heap中對象有強(qiáng)可及對象、軟可及對象、弱可及對象、虛可及對象和不可到達(dá)對象。應(yīng)用的強(qiáng)弱順序是強(qiáng)、軟、弱、和虛。對于對象是屬于哪種可及的對象,由他的最強(qiáng)的引用決定。如下
String abc=new String("abc"); //1SoftReference<String> abcSoftRef=new SoftReference<String>(abc); //2WeakReference<String> abcWeakRef = new WeakReference<String>(abc); //3abc=null; //4abcSoftRef.clear();//5
上面的代碼中
第一行在heap對中創(chuàng)建內(nèi)容為“abc”的對象,并建立abc到該對象的強(qiáng)引用,該對象是強(qiáng)可及的
第二行和第第三行分別建立對heap中對象的軟引用和弱引用,此時(shí)heap中的對象仍是強(qiáng)可及的.
第四行之后heap中對象不再是強(qiáng)可及的,變成軟可及的,同樣第五行執(zhí)行之后變成弱可及的.
SoftReference(軟引用)
軟引用是主要用于內(nèi)存敏感的高速緩存.在jvm報(bào)告內(nèi)存不足之前,會(huì)清楚所有的軟引用,這樣以來gc就有可能收集軟可及的對象,可能解決內(nèi)存吃緊問題,避免內(nèi)存溢出.什么時(shí)候會(huì)被收集,取決于gc的算法和gc運(yùn)行時(shí)可用內(nèi)存的大小.當(dāng)gc決定要收集軟引用是執(zhí)行以下過程,以上面的abcSoftRef為例.
1 首先將abcSoftRef的referent設(shè)置為null,不在引用heap中的new String("abc")對象.
2 將heap中的new String("abc")對象設(shè)置為可結(jié)束的(finalizable).
3 當(dāng)heap中的new String("abc")對象
的finalize()方法被運(yùn)行而且該對象占用的內(nèi)存被釋放, abcSoftRef
被添加到它的ReferenceQueue中.
注:對ReferenceQueue軟引用和如引用可以有可無,但是虛引用必須有.見
Reference(T paramT, ReferenceQueue<? super T>paramReferenceQueue)
WeakReference(弱引用)
當(dāng)gc碰到弱可及對象,并釋放abcWeakRef 的對的引用,收集該對象.但是gc可能需要對此運(yùn)用才能找到該若可及對象.通過如下代碼可以了明了的看出它的作用.
String abc=new String("abc");WeakReference<String> abcWeakRef = new WeakReference<String>(abc);abc=null;System.out.println("before gc: "+abcWeakRef.get());System.gc();System.out.println("after gc: "+abcWeakRef.get());運(yùn)行結(jié)果:before gc: abcafter gc: null
當(dāng)gc收集弱可及對象,執(zhí)行過程和軟可及一樣,只是gc不會(huì)根據(jù)內(nèi)存情況來決定是不是收集該對象.
PhantomRefrence(虛引用)
虛顧名思義就是沒有的意思,建立虛引用之后通過get方法返回結(jié)果始終為null,通過源代碼你會(huì)發(fā)現(xiàn),虛引用通向會(huì)把引用的對象寫進(jìn)referent,只是get方法返回結(jié)果為null.先看一下和gc交互的過程在說一下他的作用.
1 不把referent設(shè)置為null,直接把heap中的new String("abc")對象設(shè)置為可結(jié)束的(finalizable).
2 與軟引用和弱引用不同,先把PhantomRefrence對象添加到它的ReferenceQueue中.然后在釋放虛可及的對象.
你會(huì)發(fā)現(xiàn)在收集heap中的new String("abc")對象之前,你就可以做一些其他的事情.通過以下代碼可以了解他的作用.
import java.lang.ref.PhantomReference;import java.lang.ref.Reference;import java.lang.ref.ReferenceQueue;import java.lang.reflect.Field;public class Test {public static boolean isRun = true;public static void main(String[] args) throws Exception {String abc = new String("abc");System.out.println(abc.getClass() + "@" + abc.hashCode());final ReferenceQueue referenceQueue = new ReferenceQueue<String>();new Thread() {public void run() {while (isRun) {Object o = referenceQueue.poll();if (o != null) {try {Field rereferent = Reference.class.getDeclaredField("referent");rereferent.setAccessible(true);Object result = rereferent.get(o);System.out.println("gc will collect:"+ result.getClass() + "@"+ result.hashCode());} catch (Exception e) {e.printStackTrace();}}}}}.start();PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,referenceQueue);abc = null;Thread.currentThread().sleep(3000);System.gc();Thread.currentThread().sleep(3000);isRun = false;}}
結(jié)果為
聯(lián)系客服