Java中的四種引用類型

1. 概述

Java虛擬機(jī)垃圾收集這一文中,我們談到了Java中對(duì)引用的定義有如下四種:強(qiáng)引用伏伐,軟引用,弱引用晕拆,虛引用四種藐翎。接下來我們就具體談一談這四種引用。

Java中的引用類型.png

2. 強(qiáng)引用

Java語言通過引用使得我們可以直接操作堆中的對(duì)象实幕,下例中的變量str指向String實(shí)例所在的堆空間吝镣,通過str我們可以操作該對(duì)象

String str = new String("StrongReference");

強(qiáng)引用具有如下的特點(diǎn):

  1. 可以直接訪問目標(biāo)對(duì)象
  2. 所指向的對(duì)象在任何時(shí)候都不會(huì)被系統(tǒng)回收,JVM寧愿拋出OOM異常昆庇,也不會(huì)回收強(qiáng)引用所指向的對(duì)象
  3. 可能會(huì)導(dǎo)致內(nèi)存泄漏

3. 軟引用

軟引用是除了強(qiáng)引用外最強(qiáng)的引用類型末贾,我們可以通過java.lang.ref.SoftReference來使用軟引用。SoftReference實(shí)例可以保存對(duì)一個(gè)Java對(duì)象的軟引用整吆,在不妨礙垃圾收集器對(duì)該Java對(duì)象進(jìn)行回收的前提下拱撵,也就是在該對(duì)象被垃圾回收器回收之前,通過SoftReference類的get()方法可以獲得該Java對(duì)象的強(qiáng)引用掂为,一旦該對(duì)象被回收之后裕膀,get()就會(huì)返回null。

/**jvm參數(shù) :-XX:+PrintGCDetails -Xmx4m -Xms4m -Xmn4m */
public class ReferenceTest {
    public static void main(String[] args) {
        byte[] byte1 = new byte[1024 * 515];
        SoftReference softReference = new SoftReference(byte1);
        byte1 = null;
        System.gc();
        System.out.println("obj 是否被回收 勇哗? "+softReference.get());
    }
}
/********************************************************************************************/
/**
obj 是否被回收 昼扛? [B@7cd84586
Heap
 PSYoungGen      total 3072K, used 1108K [0x00000000ffc80000, 0x0000000100000000, 0x0000000100000000)
  eden space 2560K, 43% used [0x00000000ffc80000,0x00000000ffd952a8,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 512K, used 454K [0x00000000ffc00000, 0x00000000ffc80000, 0x00000000ffc80000)
  object space 512K, 88% used [0x00000000ffc00000,0x00000000ffc71898,0x00000000ffc80000)
 Metaspace       used 3231K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 352K, capacity 388K, committed 512K, reserved 1048576K
Java HotSpot(TM) 64-Bit Server VM warning: MaxNewSize (4096k) is equal to or greater than the entire heap (4096k).  A new max generation size of 3584k will be used.
*/

這是雖然進(jìn)行了一次GC但是通過軟引用還是能取得對(duì)象,接下來我們再申請(qǐng)一塊大一點(diǎn)的空間

public class ReferenceTest {
    public static void main(String[] args) {
        byte[] byte1 = new byte[1024 * 515];
        SoftReference softReference = new SoftReference(byte1);
        byte1 = null;
        System.gc();
        byte[] byte2 = new byte[1024 * 2500];
        System.out.println("obj 是否被回收 欲诺? "+softReference.get());
    }
}
/**********************************************************************************************/
/**
obj 是否被回收 抄谐? null
[Full GC (Ergonomics) [PSYoungGen: 2560K->0K(3072K)] [ParOldGen: 467K->464K(512K)] 3027K->464K(3584K), [Metaspace: 3313K->3313K(1056768K)], 0.0056548 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 3072K, used 25K [0x00000000ffc80000, 0x0000000100000000, 0x0000000100000000)
  eden space 2560K, 1% used [0x00000000ffc80000,0x00000000ffc867f0,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 85% used [0x00000000fff00000,0x00000000fff6ce98,0x00000000fff80000)
 ParOldGen       total 512K, used 464K [0x00000000ffc00000, 0x00000000ffc80000, 0x00000000ffc80000)
  object space 512K, 90% used [0x00000000ffc00000,0x00000000ffc74198,0x00000000ffc80000)
 Metaspace       used 3319K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 359K, capacity 388K, committed 512K, reserved 1048576K
*/

此時(shí),PSYoungGen(年輕代)中的2560K空間肯定是不夠用的扰法,就會(huì)觸發(fā)一次垃圾回收蛹含,當(dāng)然你也可以顯示的再調(diào)用一次gc(),經(jīng)過這次GC后軟引用已經(jīng)被回收了塞颁。因此我們可以總結(jié)出軟引用有如下特點(diǎn):

  1. 一個(gè)持軟引用的對(duì)象浦箱,不會(huì)立馬被垃圾回收器所回收。
  2. 當(dāng)堆內(nèi)存的使用率接近閾值時(shí)祠锣,才會(huì)去回收軟引用的對(duì)象酷窥。

4. 弱引用

弱引用是一種比軟引用還要弱的引用類型。在系統(tǒng)進(jìn)行GC的時(shí)候伴网,只要發(fā)現(xiàn)弱引用都會(huì)對(duì)其進(jìn)行回收蓬推。我們可以通過java.lang.ref.WeakReference來保存一個(gè)弱引用的實(shí)例。

public class ReferenceTest {
    public static void main(String[] args) {
        byte[] byte1 = new byte[1024 * 515];
        WeakReference<byte[]> weakReference = new WeakReference<>(byte1);
        byte1 = null;
        System.out.println("弱引用是否被回收 : "+weakReference.get());
        System.gc();
        System.out.println("弱引用是否被回收 : "+weakReference.get());
    }
}
/**********************************************************************************************/
/**
弱引用是否被回收 : [B@7cd84586
弱引用是否被回收 : null
*/

5. 虛引用

虛引用是所有引用類型中最弱的一種澡腾,一個(gè)持有虛引用的對(duì)象和幾乎沒有引用是一樣的沸伏,隨時(shí)可能被垃圾回收器所回收糕珊。虛引用的get方法總是會(huì)返回null。為了追蹤垃圾回收過程毅糟,虛引用必須和引用隊(duì)列一起使用红选。

public class ReferenceTest {
    public static void main(String[] args) {
        byte[] byte1 = new byte[1024 * 515];
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        PhantomReference sf = new PhantomReference<>(byte1,referenceQueue);
        byte1 = null;
        System.out.println("是否被回收"+sf.get());
        System.gc();
        System.out.println("是否被回收"+sf.get());
    }
}
/*********************************************************************************************/
/**
是否被回收null
是否被回收null
*/

6. WeakHashMap

WeakHashMap類屬于java.util包,實(shí)現(xiàn)了Map接口留特,是HashMap的一種實(shí)現(xiàn)纠脾,使用弱引用作為內(nèi)部數(shù)據(jù)的存儲(chǔ)方案。

/** -Xmx4m -Xms4m -Xmn4m  限定堆椡汕啵空間大小為4M*/
public class ReferenceTest {
    public static void main(String[] args) {
//        WeakHashMap<Object, Object> weakMap = new WeakHashMap<>();
//        for (int i = 0 ; i<10000000; i++){
//            weakMap.put(i, new byte[i]);
//        }

        HashMap<Object, Object> hashMap = new HashMap<>();
        for (int i = 0 ; i<10000000; i++){
            hashMap.put(i, new byte[i]);
        }
    }
}

通過結(jié)果我們可以發(fā)現(xiàn)苟蹈,使用WeakHashMap的代碼可以正常運(yùn)行結(jié)束,而使用HashMap的代碼則會(huì)拋出OOM異常右核,因?yàn)閃eakHashMap會(huì)在內(nèi)存使用緊張時(shí)使用弱引用慧脱,自動(dòng)釋放掉持有弱引用的內(nèi)存數(shù)據(jù),但是如果WeakHashMap的key都在系統(tǒng)里持有強(qiáng)引用贺喝,那么WeakHashMap就會(huì)跟普通的HashMap一樣菱鸥,里面的數(shù)據(jù)無法被自動(dòng)清理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末躏鱼,一起剝皮案震驚了整個(gè)濱河市氮采,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌染苛,老刑警劉巖鹊漠,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茶行,居然都是意外死亡躯概,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門畔师,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娶靡,“玉大人,你說我怎么就攤上這事看锉∽硕В” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵伯铣,是天一觀的道長艾凯。 經(jīng)常有香客問我,道長懂傀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任蜡感,我火速辦了婚禮蹬蚁,結(jié)果婚禮上恃泪,老公的妹妹穿的比我還像新娘。我一直安慰自己犀斋,他們只是感情好贝乎,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叽粹,像睡著了一般览效。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虫几,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天锤灿,我揣著相機(jī)與錄音,去河邊找鬼辆脸。 笑死但校,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的啡氢。 我是一名探鬼主播状囱,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倘是!你這毒婦竟也來了亭枷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤搀崭,失蹤者是張志新(化名)和其女友劉穎叨粘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體门坷,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宣鄙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了默蚌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冻晤。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绸吸,靈堂內(nèi)的尸體忽然破棺而出鼻弧,到底是詐尸還是另有隱情,我是刑警寧澤锦茁,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布攘轩,位于F島的核電站,受9級(jí)特大地震影響码俩,放射性物質(zhì)發(fā)生泄漏度帮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笨篷。 院中可真熱鬧瞳秽,春花似錦瞭空、人聲如沸哈肖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冕臭。三九已至腺晾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辜贵,已是汗流浹背悯蝉。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留念颈,地道東北人泉粉。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像榴芳,于是被迫代替她去往敵國和親嗡靡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一窟感、Java中的四種引用類型 JDK 1.2 開始 Java 提供了四種引用類型讨彼,分別是強(qiáng)引用、軟引用柿祈、弱引用哈误、虛...
    lxbnjupt閱讀 365評(píng)論 0 0
  • Java中有四種引用類型:StrongReference(強(qiáng)引用),SoftReference(軟引用)躏嚎,Weak...
    zhong0316閱讀 233評(píng)論 0 2
  • Java的內(nèi)存回收不需要程序員負(fù)責(zé)蜜自,JVM會(huì)在必要時(shí)啟動(dòng)Java GC完成垃圾回收。Java以便我們控制對(duì)象的生存...
    java部落閱讀 305評(píng)論 0 0
  • 因?yàn)槊β德叮允チ撕芏唷?有了一點(diǎn)獨(dú)處時(shí)光重荠,才發(fā)現(xiàn)了自我。 我們頂著別人的稱謂虚茶,干著別人的活戈鲁,去實(shí)現(xiàn)這個(gè)崗位所應(yīng)...
    magnum1985閱讀 1,858評(píng)論 0 0
  • 林野輕風(fēng)閱讀 153評(píng)論 0 4