Java 中的四种引用类型
一、背景
Java的內(nèi)存回收不需要程序員負(fù)責(zé),JVM會(huì)在必要時(shí)啟動(dòng)Java GC完成垃圾回收。Java以便我們控制對象的生存周期,提供給了我們四種引用方式,引用強(qiáng)度從強(qiáng)到弱分別為:強(qiáng)引用、軟引用、弱引用、虛引用。
?
二、簡介
1. 強(qiáng)引用 StrongReference
StrongReference是Java的默認(rèn)引用形式,使用時(shí)不需要顯示定義。任何通過強(qiáng)引用所使用的對象不管系統(tǒng)資源有多緊張,Java GC都不會(huì)主動(dòng)回收具有強(qiáng)引用的對象。
public?class?StrongReferenceTest?{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)存");//實(shí)例化10M的數(shù)組并與strongReference建立強(qiáng)引用byte[]?strongReference?=?new?byte[10*StrongReferenceTest.M];StrongReferenceTest.printlnMemory("2.實(shí)例化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);} }運(yùn)行結(jié)果:
2. 弱引用 WeakReference
如果一個(gè)對象只具有弱引用,無論內(nèi)存充足與否,Java GC后對象如果只有弱引用將會(huì)被自動(dòng)回收。
public?class?WeakReferenceTest?{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.實(shí)例化10M的數(shù)組,并建立弱引用");System.out.println("weakRerference.get()?:?"+weakRerference.get());System.gc();StrongReferenceTest.printlnMemory("3.GC后");System.out.println("weakRerference.get()?:?"+weakRerference.get());} }運(yùn)行結(jié)果:
3. 軟引用 SoftReference
軟引用和弱引用的特性基本一致, 主要的區(qū)別在于軟引用在內(nèi)存不足時(shí)才會(huì)被回收。如果一個(gè)對象只具有軟引用,Java GC在內(nèi)存充足的時(shí)候不會(huì)回收它,內(nèi)存不足時(shí)才會(huì)被回收。
public?class?SoftReferenceTest?{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.實(shí)例化10M的數(shù)組,并建立軟引用");System.out.println("softRerference.get()?:?"+softRerference.get());System.gc();SoftReferenceTest.printlnMemory("3.內(nèi)存可用容量充足,GC后");System.out.println("softRerference.get()?:?"+softRerference.get());//實(shí)例化一個(gè)4M的數(shù)組,使內(nèi)存不夠用,并建立軟引用//free=10M=4M+10M-4M,證明內(nèi)存可用量不足時(shí),GC后byte[10*m]被回收SoftReference<Object>?softRerference2?=?new?SoftReference<Object>(new?byte[4*SoftReferenceTest.M]);SoftReferenceTest.printlnMemory("4.實(shí)例化一個(gè)4M的數(shù)組后");System.out.println("softRerference.get()?:?"+softRerference.get());System.out.println("softRerference2.get()?:?"+softRerference2.get());} }運(yùn)行結(jié)果:
4. 虛引用 PhantomReference
從PhantomReference類的源代碼可以知道,它的get()方法無論何時(shí)返回的都只會(huì)是null。所以單獨(dú)使用虛引用時(shí),沒有什么意義,需要和引用隊(duì)列ReferenceQueue類聯(lián)合使用。當(dāng)執(zhí)行Java GC時(shí)如果一個(gè)對象只有虛引用,就會(huì)把這個(gè)對象加入到與之關(guān)聯(lián)的ReferenceQueue中。
public?class?PhantomReferenceTest?{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.實(shí)例化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é)果:
?
三、小結(jié)
強(qiáng)引用是 Java 的默認(rèn)引用形式,使用時(shí)不需要顯示定義,是我們平時(shí)最常使用到的引用方式。不管系統(tǒng)資源有多緊張,Java GC都不會(huì)主動(dòng)回收具有強(qiáng)引用的對象。 弱引用和軟引用一般在引用對象為非必需對象的時(shí)候使用。它們的區(qū)別是被弱引用關(guān)聯(lián)的對象在垃圾回收時(shí)總是會(huì)被回收,被軟引用關(guān)聯(lián)的對象只有在內(nèi)存不足時(shí)才會(huì)被回收。 虛引用的get()方法獲取的永遠(yuǎn)是null,無法獲取對象實(shí)例。Java GC會(huì)把虛引用的對象放到引用隊(duì)列里面。可用來在對象被回收時(shí)做額外的一些資源清理或事物回滾等處理。 由于無法從虛引獲取到引用對象的實(shí)例。它的使用情況比較特別,所以這里不把虛引用放入表格進(jìn)行對比。這里對強(qiáng)引用、弱引用、軟引用進(jìn)行對比:
| 強(qiáng)引用 | 不被回收 | 不被回收 |
| 弱引用 | 被回收 | 被回收 |
| 軟引用 | 不被回收 | 被回收 |
總結(jié)
以上是生活随笔為你收集整理的Java 中的四种引用类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SaaS业务的价值评估
- 下一篇: Web 安全漏洞之 XSS 攻击,Jav