內(nèi)存泄漏:使用弱應(yīng)用處理外部類引用

public class SampleActivity extends Activity {

  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<SampleActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}

這里Handler為什么要用弱引用來持有Activity的引用?和使用軟引用有什么區(qū)別?

這里使用弱引用持有Activity,就是表示Handler不會占用著對activity的引用而導(dǎo)致系統(tǒng)無法回收,只要系統(tǒng)來回收這個Activity就能回收掉僧叉。

在我的理解,使用弱引用而不是軟引用棺榔,表示Handler將Activity回收權(quán)完全地交給組件管理系統(tǒng):系統(tǒng)什么時候回收Activity我不知道瓶堕,反正我不占用,只要你GC來回收時就能回收掷豺。

如果Activity被回收了捞烟,會對Handler業(yè)務(wù)邏輯有影響嗎?這里需要考慮到情形当船。什么時候GC會來回收Activity题画?這時應(yīng)該是用戶已經(jīng)退出或者跳出了這個Activity,而內(nèi)存緊張德频,組件管理系統(tǒng)判斷需要這個Activity了苍息。

Handler的handleMessage()一般是在異步消息返回后更新數(shù)據(jù)操作的,這時如果Activity已經(jīng)隱入后臺了壹置,一般也不再需要UI或數(shù)據(jù)的更新了竞思。當(dāng)然如果需要這個Activity常駐內(nèi)存,當(dāng)用戶回到這個Activity可以看到更新后的數(shù)據(jù)钞护,可以使用其他方法盖喷。

強(qiáng)引用

只要某個對象有強(qiáng)引用與之關(guān)聯(lián),JVM必定不會回收這個對象难咕,即使在內(nèi)存不足的情況下课梳,JVM寧愿拋出OutOfMemory錯誤也不會回收這種對象。

如果想中斷強(qiáng)引用和某個對象之間的關(guān)聯(lián)余佃,可以顯示地將引用賦值為null暮刃,這樣一來的話,JVM在合適的時間就會回收該對象爆土。

軟引用

軟引用在Java中用java.lang.ref.SoftReference類來表示椭懊。

對于軟引用關(guān)聯(lián)著的對象,只有在內(nèi)存不足的時候JVM才會回收該對象步势。因此氧猬,這一點可以很好地用來解決OOM的問題背犯,并且這個特性很適合用來實現(xiàn)緩存:比如網(wǎng)頁緩存、圖片緩存等狂窑。

軟引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用媳板,如果軟引用所引用的對象被JVM回收桑腮,這個軟引用就會被加入到與之關(guān)聯(lián)的引用隊列中泉哈。

import java.lang.ref.SoftReference;
 
public class Main {
    public static void main(String[] args) {
         
        SoftReference<String> sr = new SoftReference<String>(new String("hello"));
        System.out.println(sr.get());
    }
}

弱引用

弱引用用java.lang.ref.WeakReference類來表示。

當(dāng)JVM進(jìn)行垃圾回收時破讨,無論內(nèi)存是否充足丛晦,都會回收被弱引用關(guān)聯(lián)的對象。

import java.lang.ref.WeakReference;
 
public class Main {
    public static void main(String[] args) {
     
        WeakReference<String> sr = new WeakReference<String>(new String("hello"));
         
        System.out.println(sr.get());
        System.gc(); //通知JVM的gc進(jìn)行垃圾回收
        System.out.println(sr.get());
    }
}

輸出結(jié)果

hello
null

第二個輸出結(jié)果是null提陶,這說明只要JVM進(jìn)行垃圾回收烫沙,被弱引用關(guān)聯(lián)的對象必定會被回收掉。

虛引用

虛引用在java中用java.lang.ref.PhantomReference類表示隙笆。

虛引用并不影響對象的生命周期锌蓄。如果一個對象與虛引用關(guān)聯(lián),則跟沒有引用與之關(guān)聯(lián)一樣撑柔,在任何時候都可能被垃圾回收器回收瘸爽。

要注意的是,虛引用必須和引用隊列關(guān)聯(lián)使用铅忿,當(dāng)垃圾回收器準(zhǔn)備回收一個對象時剪决,如果發(fā)現(xiàn)它還有虛引用,就會把這個虛引用加入到與之 關(guān)聯(lián)的引用隊列中檀训。程序可以通過判斷引用隊列中是否已經(jīng)加入了虛引用柑潦,來了解被引用的對象是否將要被垃圾回收。如果程序發(fā)現(xiàn)某個虛引用已經(jīng)被加入到引用隊列峻凫,那么就可以在所引用的對象的內(nèi)存被回收之前采取必要的行動渗鬼。

軟引用和弱引用的區(qū)別

它們都是用來描述非必需對象的,但是被軟引用關(guān)聯(lián)的對象只有在內(nèi)存不足時才會被回收荧琼,而被弱引用關(guān)聯(lián)的對象在JVM進(jìn)行垃圾回收時總會被回收譬胎。

引用類的使用

在SoftReference類中,有三個方法铭腕,兩個構(gòu)造方法和一個get方法(WekReference類似):

兩個構(gòu)造方法:

public SoftReference(T referent) {
    super(referent);
    this.timestamp = clock;
}
 
public SoftReference(T referent, ReferenceQueue<? super T> q) {
    super(referent, q);
    this.timestamp = clock;
}

get方法用來獲取與軟引用關(guān)聯(lián)的對象的引用银择,如果該對象被回收了,則返回null累舷。

在使用軟引用和弱引用的時候浩考,我們可以顯示地通過System.gc()來通知JVM進(jìn)行垃圾回收。要注意的是被盈,雖然發(fā)出了通知析孽,JVM不一定會立刻執(zhí)行搭伤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袜瞬,隨后出現(xiàn)的幾起案子怜俐,更是在濱河造成了極大的恐慌,老刑警劉巖邓尤,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拍鲤,死亡現(xiàn)場離奇詭異,居然都是意外死亡汞扎,警方通過查閱死者的電腦和手機(jī)季稳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澈魄,“玉大人景鼠,你說我怎么就攤上這事”陨龋” “怎么了铛漓?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鲫构。 經(jīng)常有香客問我浓恶,道長,這世上最難降的妖魔是什么芬迄? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任问顷,我火速辦了婚禮,結(jié)果婚禮上禀梳,老公的妹妹穿的比我還像新娘杜窄。我一直安慰自己,他們只是感情好算途,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布塞耕。 她就那樣靜靜地躺著,像睡著了一般嘴瓤。 火紅的嫁衣襯著肌膚如雪扫外。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天廓脆,我揣著相機(jī)與錄音筛谚,去河邊找鬼。 笑死停忿,一個胖子當(dāng)著我的面吹牛驾讲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼吮铭,長吁一口氣:“原來是場噩夢啊……” “哼时迫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谓晌,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤掠拳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后纸肉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溺欧,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年毁靶,在試婚紗的時候發(fā)現(xiàn)自己被綠了胧奔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡预吆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胳泉,到底是詐尸還是另有隱情拐叉,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布扇商,位于F島的核電站凤瘦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏案铺。R本人自食惡果不足惜蔬芥,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望控汉。 院中可真熱鬧笔诵,春花似錦、人聲如沸姑子。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽街佑。三九已至谢翎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沐旨,已是汗流浹背森逮。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留磁携,地道東北人褒侧。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親璃搜。 傳聞我的和親對象是個殘疾皇子拖吼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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