1. OOM(內存溢出)和Memory Leak(內存泄露)有什麼關係?
OOM多是由於Memory Leak,也多是你的應用自己就比較耗內存(好比圖片瀏覽型的)。因此,出現OOM不必定是Memory Leak。 html
一樣,Memory Leak也不必定就會致使OOM,若是泄露的速度很慢,可能還沒用完可用內存應用就被重啓了,那就不會OOM咯。固然了,有bug解決了最好。 java
2. 什麼是shallow heap與retained heap?
- shallow heap:你自身佔了多少內存,好比你有一個int屬性,就佔4字節。不包括你引用的其餘對象。
- retained heap:若是你被銷燬,總共會釋放多少內存。這些因你存在被佔據的空間就是retained heap。
3. 什麼是GC roots?
GC的時候,是從這些節點開始遍歷,不停的尋找其子節點直到結束。而後把不能遍歷到的節點釋放。這些遍歷的起點(注意,可不是一個哦)就叫作GC roots。 android
那,對於java來講,誰是GC roots?簡單點說(不是那麼準確)包括如下幾種: app
- 棧上面的局部變量
- 棧上面的函數參數變量
- 全部由Bootstrap Loader加載的類變量
- 另外,JNI相關的也會有
- 更多詳細解釋請看這篇博客
4. 怎樣使用MAT定位內存泄露?
4.1 看Histogram(類統計圖) 異步
對於Android程序來講,內存泄露一般都會牽扯到activity。所以,dump以前,能夠多旋轉幾回屏幕並反覆的進出可能有問題的activity,讓問題儘量的凸現。
經過Histogram咱們能夠看每一個類有多少個實例,shallow和retained heap分別有多大。若是隻是看java的基礎類型和framework的類,沒有什麼意義,必定要過濾出本身的類型,以下圖 ide
發現LeakInnerClassActivity產生了9個實例,必定是被hold住了。 函數
4.2 看Dominator Tree spa
怎樣使用還沒弄清楚,感受和histogram比沒啥特點捏,嘿嘿 code
4.3 對比heap dumps,能夠更快的定位內存泄露的位置。操做步驟: orm
- 打開一個HPROF文件,切換到histogram視圖
- 在Navigation View中右鍵點擊histogram,選擇Add to compare basket
- 打開另外一個HPROF文件,並重覆上一個步驟
- 對比兩次heap dumps的內容,看下圖,LeakInnerClassActivity的實例又增長了一個。而我僅僅是又啓動了一次該Activity,因此問題顯而易見。
參考:Memory Analysis for Android Applications
5. 內部類怎樣使用纔會產生內存泄露,以及由此衍生的AsyncTask、Handler問題如何解決?
- 若是非靜態內部類的方法中,有生命週期大於其所在類的,那就有問題了。好比:AsyncTask、Handler,這兩個類都是方便開發者執行異步任務的,可是,這兩個都跳出了Activity/Fragment的生命週期。
- 爲何?由於非靜態內部類會自動持有一個所屬類的實例,若是所屬類的實例已經結束生命週期,但內部類的方法仍在執行,就會hold其主體。也就使主體不能被釋放,亦即內存泄露。
- 靜態類呢?靜態類編譯後和非內部類是同樣的,有本身獨立的類名。不會悄悄引用所屬類的實例,因此就不容易泄露。
//首先,靜態類
static class IncomingHandler extends Handler {
//其次,弱引用
private final WeakReference<UDPListenerService> mService;
IncomingHandler(UDPListenerService service) {
mService = new WeakReference<UDPListenerService>(service);
}
@Override
public void handleMessage(Message msg) {
UDPListenerService service = mService.get();
if (service != null) {
service.handleMessage(msg);
}
}
}
6. 圖片致使的OOM如何解決?
- 加載時使用option,用多大,載入多大。
- res目錄下的圖片也是同樣,及時清理過大的圖片資源。
- 若是還有問題,就想辦法把不可見的資源釋放掉,好比,TabActivity中不可見的Tab,ViewPager中的Fragment。
- 若是activity的圖片資源較多,須要考慮屏幕旋轉時,銷燬已有資源。請參考這篇文章
7. 須要context的時候用activity仍是application?
- 看使用的週期是否在activity週期內,若是超出,必須用application;常見的情景包括:AsyncTask,Thread,第三方庫初始化等等。
- 還有些情景,只能用activity:好比,對話框,各類View,須要startActivity的等。
- 總之,儘量使用Application。參考stackoverflow
8. 何時須要手動將變量設置爲NULL?
- 類變量,一旦用完,儘快釋放。由於類的存活時間最長,因此,佔用的資源越少越好;
- 比較耗時且耗內存的方法內的局部變量,好比,圖片處理的方法,每一個bitmap對象用完就及時丟棄。儘量讓gc介入。