Java中的四種引用類型

Java的內(nèi)存回收不需要程序員負(fù)責(zé),JVM會在必要時啟動Java GC完成垃圾回收。Java以便我們控制對象的生存周期,提供給了我們四種引用方式,引用強(qiáng)度從強(qiáng)到弱分別為:強(qiáng)引用、軟引用、弱引用、虛引用。

二、簡介

1.強(qiáng)引用 StrongReference

StrongReference是Java的默認(rèn)引用形式,使用時不需要顯示定義。任何通過強(qiáng)引用所使用的對象不管系統(tǒng)資源有多緊張,Java GC都不會主動回收具有強(qiáng)引用的對象。

public static int M = 1024*1024;

public static void printlnMemory(String tag){
    Runtime runtime = Runtime.getRuntime();
    int M = StrongReferenceTest.M;
    System.out.println("\n"+tag+":");
    System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
}

public static void main(String[] args){
    StrongReferenceTest.printlnMemory("1.原可用內(nèi)存和總內(nèi)存");

    //實例化10M的數(shù)組并與strongReference建立強(qiáng)引用
    byte[] strongReference = new byte[10*StrongReferenceTest.M];
    StrongReferenceTest.printlnMemory("2.實例化10M的數(shù)組,并建立強(qiáng)引用");
    System.out.println("strongReference : "+strongReference);

    System.gc();
    StrongReferenceTest.printlnMemory("3.GC后");
    System.out.println("strongReference : "+strongReference);

    //strongReference = null;后,強(qiáng)引用斷開了
    strongReference = null;
    StrongReferenceTest.printlnMemory("4.強(qiáng)引用斷開后");
    System.out.println("strongReference : "+strongReference);

    System.gc();
    StrongReferenceTest.printlnMemory("5.GC后");
    System.out.println("strongReference : "+strongReference);
    }

}</pre>

運(yùn)行結(jié)果:

image

</figure>

2.弱引用 WeakReference

如果一個對象只具有弱引用,無論內(nèi)存充足與否,Java GC后對象如果只有弱引用將會被自動回收。

public static int M = 1024*1024;

public static void printlnMemory(String tag){
    Runtime runtime = Runtime.getRuntime();
    int M = WeakReferenceTest.M;
    System.out.println("\n"+tag+":");
    System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
}

public static void main(String[] args){  
    WeakReferenceTest.printlnMemory("1.原可用內(nèi)存和總內(nèi)存");

    //創(chuàng)建弱引用
    WeakReference<Object> weakRerference = new WeakReference<Object>(new byte[10*WeakReferenceTest.M]);   
    WeakReferenceTest.printlnMemory("2.實例化10M的數(shù)組,并建立弱引用");
    System.out.println("weakRerference.get() : "+weakRerference.get());

    System.gc();
    StrongReferenceTest.printlnMemory("3.GC后");
    System.out.println("weakRerference.get() : "+weakRerference.get());
}   

}</pre>

運(yùn)行結(jié)果:

image

3.軟引用 SoftReference

軟引用和弱引用的特性基本一致, 主要的區(qū)別在于軟引用在內(nèi)存不足時才會被回收。如果一個對象只具有軟引用,Java GC在內(nèi)存充足的時候不會回收它,內(nèi)存不足時才會被回收。

public static int M = 1024*1024;

public static void printlnMemory(String tag){
    Runtime runtime = Runtime.getRuntime();
    int M = StrongReferenceTest.M;
    System.out.println("\n"+tag+":");
    System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
}

public static void main(String[] args){
    SoftReferenceTest.printlnMemory("1.原可用內(nèi)存和總內(nèi)存");

    //建立軟引用
    SoftReference<Object> softRerference = new SoftReference<Object>(new byte[10*SoftReferenceTest.M]);
    SoftReferenceTest.printlnMemory("2.實例化10M的數(shù)組,并建立軟引用");
    System.out.println("softRerference.get() : "+softRerference.get());

    System.gc();  
    SoftReferenceTest.printlnMemory("3.內(nèi)存可用容量充足,GC后");
    System.out.println("softRerference.get() : "+softRerference.get());  

    //實例化一個4M的數(shù)組,使內(nèi)存不夠用,并建立軟引用
    //free=10M=4M+10M-4M,證明內(nèi)存可用量不足時,GC后byte[10*m]被回收
    SoftReference<Object> softRerference2 = new SoftReference<Object>(new byte[4*SoftReferenceTest.M]);
    SoftReferenceTest.printlnMemory("4.實例化一個4M的數(shù)組后");
    System.out.println("softRerference.get() : "+softRerference.get());
    System.out.println("softRerference2.get() : "+softRerference2.get());  
 } 

運(yùn)行結(jié)果:

image

4.虛引用 PhantomReference

從PhantomReference類的源代碼可以知道,它的get()方法無論何時返回的都只會是null。所以單獨(dú)使用虛引用時,沒有什么意義,需要和引用隊列ReferenceQueue類聯(lián)合使用。當(dāng)執(zhí)行Java GC時如果一個對象只有虛引用,就會把這個對象加入到與之關(guān)聯(lián)的ReferenceQueue中。

public static int M = 1024*1024;

public static void printlnMemory(String tag){
    Runtime runtime = Runtime.getRuntime();
    int M = PhantomReferenceTest.M;
    System.out.println("\n"+tag+":");
    System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
}

public static void main(String[] args) throws InterruptedException {

    PhantomReferenceTest.printlnMemory("1.原可用內(nèi)存和總內(nèi)存");
    byte[] object = new byte[10*PhantomReferenceTest.M];        
    PhantomReferenceTest.printlnMemory("2.實例化10M的數(shù)組后");

    //建立虛引用
    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
    PhantomReference<Object> phantomReference = new PhantomReference<Object>(object,referenceQueue);  

    PhantomReferenceTest.printlnMemory("3.建立虛引用后");
    System.out.println("phantomReference : "+phantomReference); 
    System.out.println("phantomReference.get() : "+phantomReference.get());
    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());

    //斷開byte[10*PhantomReferenceTest.M]的強(qiáng)引用
    object = null;  
    PhantomReferenceTest.printlnMemory("4.執(zhí)行object = null;強(qiáng)引用斷開后");

    System.gc();
    PhantomReferenceTest.printlnMemory("5.GC后");
    System.out.println("phantomReference : "+phantomReference); 
    System.out.println("phantomReference.get() : "+phantomReference.get());
    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());       

    //斷開虛引用
    phantomReference = null;
    System.gc(); 
    PhantomReferenceTest.printlnMemory("6.斷開虛引用后GC");
    System.out.println("phantomReference : "+phantomReference);
    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());           
}

運(yùn)行結(jié)果:

image

三、小結(jié)

強(qiáng)引用是 Java 的默認(rèn)引用形式,使用時不需要顯示定義,是我們平時最常使用到的引用方式。不管系統(tǒng)資源有多緊張,Java GC都不會主動回收具有強(qiáng)引用的對象。 弱引用和軟引用一般在引用對象為非必需對象的時候使用。它們的區(qū)別是被弱引用關(guān)聯(lián)的對象在垃圾回收時總是會被回收,被軟引用關(guān)聯(lián)的對象只有在內(nèi)存不足時才會被回收。 虛引用的get()方法獲取的永遠(yuǎn)是null,無法獲取對象實例。Java GC會把虛引用的對象放到引用隊列里面??捎脕碓趯ο蟊换厥諘r做額外的一些資源清理或事物回滾等處理。 由于無法從虛引獲取到引用對象的實例。它的使用情況比較特別,所以這里不把虛引用放入表格進(jìn)行對比。這里對強(qiáng)引用、弱引用、軟引用進(jìn)行對比:

引用類型 GC時JVM內(nèi)存充足 GC時JVM內(nèi)存不足
強(qiáng)引用 不被回收 不被回收
弱引用 被回收 被回收
軟引用 不被回收 被回收

歡迎加入學(xué)習(xí)交流群569772982,大家一起學(xué)習(xí)交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容