Java的四種引用:強(qiáng)軟弱虛

java內(nèi)存管理分為內(nèi)存分配和內(nèi)存回收,都不需要程序員負(fù)責(zé),垃圾回收的機(jī)制主要是看對象是否有引用指向該對象

  • java對象的引用包括
    強(qiáng)引用货邓,軟引用笙隙,弱引用,虛引用
  • Java中提供這四種引用類型主要有兩個目的:
    1. 是可以讓程序員通過代碼的方式?jīng)Q定某些對象的生命周期;
    2. 是有利于JVM進(jìn)行垃圾回收。

一、 強(qiáng)引用(StrongReference)

  • 強(qiáng)引用是使用最普遍的引用巴柿。只要某個對象有強(qiáng)引用與之關(guān)聯(lián),JVM必定不會回收這個對象死遭,即使在內(nèi)存不足的情況下广恢,JVM寧愿拋出OutOfMemory錯誤也不會回收這種對象
    如下:
        Object object =new Object();
        String str ="hello";

如果想中斷強(qiáng)引用和某個對象之間的關(guān)聯(lián),可以顯示地將引用賦值為null殃姓,這樣一來的話袁波,JVM在合適的時間就會回收該對象瓦阐,如下:

        object = null;
        str = null;

再看一下源碼中如何解決強(qiáng)引用轉(zhuǎn)為軟引用后的回收

    /**
     * 這是ArrayList中的清空數(shù)組的方法
     */
    private transient Object[] elementData;
    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

注:在ArrayList類中定義了一個私有的變量elementData數(shù)組,在調(diào)用方法清空數(shù)組時可以看到為每個數(shù)組內(nèi)容賦值為null篷牌。不同于elementData=null睡蟋,強(qiáng)引用仍然存在,避免在后續(xù)調(diào)用 add()等方法添加元素時進(jìn)行重新的內(nèi)存分配枷颊。使用如clear()方法中釋放內(nèi)存的方法對數(shù)組中存放的引用類型特別適用戳杀,這樣就可以及時釋放內(nèi)存。

二夭苗、 軟引用(SoftReference)

  • 軟引用是用來描述一些有用但并不是必需的對象信卡,在Java中用java.lang.ref.SoftReference類來表示。只有在內(nèi)存不足的時候JVM才會回收該對象题造。
    如下:
        String str=new String("abc");                                     // 強(qiáng)引用
        SoftReference<String> softRef=new SoftReference<String>(str);     // 軟引用

當(dāng)內(nèi)存不足時傍菇,等價于:

     If(JVM.內(nèi)存不足()) {
         str = null;  // 轉(zhuǎn)換為軟引用
         System.gc(); // 垃圾回收器進(jìn)行回收
      }
  • 因此,這一點(diǎn)可以很好地用來解決OOM的問題界赔,并且這個特性很適合用來實(shí)現(xiàn)緩存:比如網(wǎng)頁緩存丢习、圖片緩存等。

在瀏覽頁面時淮悼,我們會經(jīng)常使用回退功能咐低,通常有兩種程序?qū)崿F(xiàn)方式:
(1)將用戶的過去查看過的用戶信息保存在內(nèi)存中,每個存儲用戶信息的Java對象的生命周期貫穿整個應(yīng)用程序的始終袜腥;缺陷:這樣會造成內(nèi)存的大量浪費(fèi)见擦,甚至?xí)斐蓛?nèi)存溢出。
(2)如果一個頁面瀏覽結(jié)束羹令,就對其進(jìn)行內(nèi)容的回收鲤屡,只存儲當(dāng)前頁面的用戶信息,當(dāng)用戶進(jìn)行回退操作時福侈,重新構(gòu)建該用戶信息执俩;缺陷:即使垃圾收集線程還沒有進(jìn)行垃圾收集,存儲用戶信息的對象仍然完好地保存在內(nèi)存中癌刽,應(yīng)用程序也要重新構(gòu)建一個對象。
注:我們大都知道尝丐,訪問磁盤文件显拜、訪問網(wǎng)絡(luò)資源、查詢數(shù)據(jù)庫等操作都是影響應(yīng)用程序執(zhí)行性能的重要因素爹袁,如果能重新獲取那些尚未被回收的Java對象的引用远荠,必將減少不必要的訪問,大大提高程序的運(yùn)行速度失息。

  • 因此看一下使用軟引用如何解決該問譬淳,如下瀏覽器網(wǎng)頁緩存實(shí)例:
        Browser prev = new Browser();               // 獲取頁面進(jìn)行瀏覽
        SoftReference sr = new SoftReference(prev); // 瀏覽完畢后置為軟引用
        if (sr.get() != null) {
            rev = (Browser)sr.get();                // 還沒有被回收器回收档址,直接獲取
        } else {
            prev = new Browser();                   // 由于內(nèi)存吃緊,軟引用對象被回收
            sr = new SoftReference(prev);           // 重新構(gòu)建
        }
  • 軟引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用邻梆,如果軟引用所引用的對象被垃圾回收器回收守伸,Java虛擬機(jī)就會把這個軟引用加入到與之關(guān)聯(lián)的引用隊列中。

三浦妄、弱引用(WeakReference)

  • 只具有弱引用的對象擁有更短暫的生命周期尼摹。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象剂娄,不管當(dāng)前內(nèi)存空間足夠與否蠢涝,都會回收它的內(nèi)存。不過阅懦,由于垃圾回收器是一個優(yōu)先級很低的線程和二,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象。
        // 創(chuàng)建一個引用隊列
        ReferenceQueue<String> rq = new ReferenceQueue<String>();
        // 實(shí)現(xiàn)一個弱引用耳胎,將強(qiáng)引用類型hello和是實(shí)例化的rq放到弱引用實(shí)現(xiàn)里面
        WeakReference<String> sr = new WeakReference<String>(new String("hello"), rq);
        // 通過弱引用get方法獲取強(qiáng)引用中創(chuàng)建的內(nèi)存空間hello值
        System.out.println(sr.get());
        System.gc();                //通知JVM的gc進(jìn)行垃圾回收
        System.out.println(sr.get());

四惯吕、 虛引用(PhantomReference)

  • 虛引用也稱為幻影引用,一個對象是都有虛引用的存在都不會對生存時間都構(gòu)成影響场晶,也無法通過虛引用來獲取對一個對象的真實(shí)引用混埠。唯一的用處:能在對象被GC時收到系統(tǒng)通知,JAVA中用PhantomReference來實(shí)現(xiàn)虛引用
  • 虛引用必須和引用隊列 (ReferenceQueue)聯(lián)合使用诗轻。當(dāng)垃圾回收器準(zhǔn)備回收一個對象時钳宪,如果發(fā)現(xiàn)它還有虛引用,就會在回收對象的內(nèi)存之前扳炬,把這個虛引用加入到與之 關(guān)聯(lián)的引用隊列中吏颖。

程序可以通過判斷引用隊列中是否已經(jīng)加入了虛引用,來了解被引用的對象是否將要被垃圾回收恨樟。如果程序發(fā)現(xiàn)某個虛引用已經(jīng)被加入到引用隊列半醉,那么就可以在所引用的對象的內(nèi)存被回收之前采取必要的行動。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末劝术,一起剝皮案震驚了整個濱河市缩多,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌养晋,老刑警劉巖衬吆,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绳泉,居然都是意外死亡逊抡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門零酪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冒嫡,“玉大人拇勃,你說我怎么就攤上這事⌒⒘瑁” “怎么了方咆?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長胎许。 經(jīng)常有香客問我峻呛,道長,這世上最難降的妖魔是什么辜窑? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任钩述,我火速辦了婚禮,結(jié)果婚禮上穆碎,老公的妹妹穿的比我還像新娘牙勘。我一直安慰自己,他們只是感情好所禀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布方面。 她就那樣靜靜地躺著,像睡著了一般色徘。 火紅的嫁衣襯著肌膚如雪恭金。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天褂策,我揣著相機(jī)與錄音横腿,去河邊找鬼。 笑死斤寂,一個胖子當(dāng)著我的面吹牛耿焊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遍搞,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼罗侯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了溪猿?” 一聲冷哼從身側(cè)響起钩杰,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诊县,沒想到半個月后榜苫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翎冲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了媳荒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抗悍。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡驹饺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缴渊,到底是詐尸還是另有隱情赏壹,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布衔沼,位于F島的核電站蝌借,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏指蚁。R本人自食惡果不足惜菩佑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凝化。 院中可真熱鬧稍坯,春花似錦、人聲如沸搓劫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枪向。三九已至勤揩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秘蛔,已是汗流浹背陨亡。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缠犀,地道東北人数苫。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像辨液,于是被迫代替她去往敵國和親虐急。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

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