android內存泄露-總結

1.GC root:java

一、  Class:由系統的類加載器加載的類對象android

二、  Static Fields網絡

三、  Thread:活着的線程ide

四、  Stack Local: java方法的局部變量或參數函數

五、  JNI Local: JNI方法中的局部引用工具

六、  JNI Global: 全局的JNI引用post

七、  Monitor used: 用於同步的監控對象google

八、Help by VM: 用於JVM特殊目的由GC保留的對象spa

 

 

 

 

 

 

 

 

每一個應用最大可以使用的堆內存受到Android系統的限制:getMemoryClass()線程

2.context內存泄露

 一、若是一個類持有Context對象的強引用,就須要檢查其生存週期是否比Context對象更長。不然就可能發生Context泄漏。

 二、View持有其建立所在Context對象的引用,若是將View對象傳遞給其它生存週期比View所在Context更長的強引用,就可能會引發內存泄漏。

例如View#setTag(int, Object)的內存泄漏https://code.google.com/p/android/issues/detail?id=18273

 三、把Context對象賦給static變量。

避免Context對象泄漏Checklist

      一、檢查全部持有對Context對象強引用的對象的生命週期是否超出其所持有的Context對象的生命週期。

      二、檢查有沒有把View傳出到View所在Context以外的地方,若是有的話就須要檢查生命週期。

      三、工具類中最好不要有Context成員變量,儘可能在調用函數時直接經過調用參數傳入。若是必須有Context成員變量時,能夠考慮使用WeakReference來引用Context對象。

      四、View持有其建立所在Context對象的引用,若是將View對象傳遞給其它生存週期比View所在Context更長的強引用,就可能會引發內存泄漏。

      五、  檢查把Context或者View對象賦給static變量的地方,看是否有Context泄漏。

      六、檢查全部把View放入容器類的地方(特別是static容器類),看是否有內存泄漏。七、使用WeakHashMap也須要注意有沒有value-key的引用。

      七、儘可能使用ApplicationContext。

 

 

 

 

 

 

 

 

 

 

 

 

3.handler泄露

發送到Handler的Message其實是加入到了主線程的消息隊列等待處理,每個Message持有其目標Handler的強引用。

如咱們一般使用的匿名內部類Handler

Handler mHandler = new Handler() {
    @Override
    public voidhandleMessage(Message msg) {
       mImageView.setImageBitmap(mBitmap);
    }
}

 

上面是一段簡單的Handler的使用。當使用內部類(包括匿名類)來建立Handler的時候,Handler對象會隱式地持有一個外部類對象(一般是一個Activity)的引用,由於View會依附着一個Activity。而Handler一般會伴隨着一個耗時的後臺線程(例如從網絡拉取圖片)一塊兒出現,這個後臺線程在任務執行完畢(例如圖片下載完畢)以後,經過消息機制通知Handler,而後Handler把圖片更新到界面。然而,若是用戶在網絡請求過程當中關閉了Activity,正常狀況下,Activity再也不被使用,它就有可能在GC檢查時被回收掉,但因爲這時線程還沒有執行完,而該線程持有Handler的引用(否則它怎麼發消息給Handler?),這個Handler又持有Activity的引用,就致使該Activity沒法被回收(即內存泄露),直到網絡請求結束(例如圖片下載完畢)。另外,若是你執行了Handler的postDelayed()方法,該方法會將你的Handler裝入一個Message,並把這條Message推到MessageQueue中,那麼在你設定的delay到達以前,會有一條MessageQueue -> Message -> Handler -> Activity的鏈,致使你的Activity被持有引用而沒法被回收。

固然,應爲是Handler對外部持有引用的緣由,咱們就能夠將Activity設置爲一個弱引用,在沒必要要的時候,再也不執行內部方法。

publicclass WeakRefHandler extends Handler
{
    WeakReference<Context> mWeakContext;
 
    public WeakRefHandler(Context context)
    {
        mWeakContext = newWeakReference<Context>(context);
    }
 
    @Override
    public void handleMessage(Message msg)
    {
        if((mWeakContext.get() instanceofActivity )&& ((Activity)mWeakContext.get()).isFinishing())
                return ;
        if(mWeakContext==null){
            return ;
        }
        super.handleMessage(msg);
    }
}
相關文章
相關標籤/搜索