OOM總結

本文主要信息是來自互聯網,我只是本身作了一點總結和摘要。java

OOM發生的緣由android

簡單的說經過不一樣的內存分配方式對不一樣的對象進行操做,會由於android系統版本的差別而產生不一樣的行爲。主要是2.0和4.0有較大的變化。web

在2.x系統中,dalvik allocated  + external allocated + 新分配的大小>= getMemoryClass() 就會發生OOM。編程

在4.x系統中,廢除了external計數器,相似Bitmap的分配改到了Dalvik的java Heap 中申請,只要allocate + 新分配的內存>=getMemoryClass就會發生OOM。緩存

如何避免OOM網絡

根據上面的介紹,避免OOM就是下降內存佔用,和內存對象的重複利用,避免對象內存泄露,優化內存使用策略。多線程

1. 減少對象的內存佔用app

1)儘量的使用android系統特有的對象,好比能夠用arrayMap 和 SparseArray 代替hasMap,hasMap須要一個額外的對象來記錄Mapping操做。SparseArray 更加高效,避免了對key和value的自動裝箱和解箱。框架

2)避免使用Enum枚舉,在android 官方文檔裏面就提到枚舉一般須要更多的內存比 static constants。佈局

3) 減小Bitmap對象的內存佔用,通常狀況下一般有2個措施:

  inSampleSize,縮放比例,在把圖片載入內存以前,咱們就先計算一個合適的縮放比例

  decode format, 選擇合適的解碼格式ARGB_8888,每一個像素點佔32位,ARGB_4444每一個像素點佔16位,RGB_565每一個像素點佔16位,ALPHA_8只有透明度,沒有顏色。8位一個字節,因此在圖片過大的時候,適當選擇16位的解碼格式,能夠減小一半的圖片內存佔用。

4)可使用更小的圖片,特別是在listview中,能夠用較小的圖片顯示,只用在用戶須要看大圖的時候,才顯示大圖。

2. 內存對象的重複使用

1)android 系統自己內置了不少資源,好比字符串,顏色,圖片,動畫,樣式等,這些資源能夠直接使用,可是不足之處是不一樣的android版本之間會有差別。

2) 注意在listview等對convertView的重複使用

3) Bitmap對象的複用,在listview等顯示大量圖片的控件裏,須要使用LRU的機制來緩存處理好的bitmap。

利用inBitmap的高級特性提升android系統在bitmap分配與釋放上的執行效率,在android 3.0和4.0上存在一些使用限制,inBitmap能夠通知Bitmap解碼去嘗試使用已經存在的內存區域,這樣就達到了圖片內存重用的效果。InBitmap的使用限制以下:

1. 在SDK11-18之間,重用的Bitmap大小必須一致,在19之後,新申請的bitmap必須小於或者等於已經賦值過的Bitmap大小。

2. 新申請的bitmap必須和舊的bitmap具備相同的解碼格式。不過能夠經過創建bitmap對象池來解決這個問題。

4)避免在onDraw裏面執行對象建立,由於onDraw會被頻繁調用,這樣就頻繁執行對象建立,而迅速增長內存使用,頻繁的GC,致使內存抖動。

5)使用StringBuilder代替String作字符的拼接

3 避免內存泄露

開源控件LeakCanary開源控件,能夠很好的幫助咱們發現內存泄露狀況。

 

1)注意Activity的泄露,這個是最嚴重的問題,通常有2種狀況會致使內存泄露:

1.內部類引用致使Activity泄露:最典型的是Handler致使的,若是handler中有延遲的任務或者等待執行的任務隊列過長,都有可能形成Activity泄露,解決方式: 在退出UI以前,執行remove Handler消息隊列中的消息和runnable對象,或者使用static + weakReference的方式斷開Handler與Activity之間存在的引用關係的目的。

2. Activity Context被傳遞到其餘實體中,也可能致使自身被引用而發生泄露。

2)考慮使用Application Context而不是Activity Context

3)注意臨時bitmap對象的及時回收,由於在建立一個臨時的相對較大的bitmap對象,在進過變換後獲得新的bitmap對象,那麼應該儘快回收原始的bitmap,釋放空間,儘可能不要使用createBitmap方法。

4)注意監聽器的註銷,特別是手動添加的監聽器要及時remove。

5)注意緩存容易中的對象泄露,不要的緩存應該馬上釋放。

6)webview泄露,不一樣版本,不一樣廠商出貨的ROM裏面webview都存在很大差別,因此最好是webview開啓另一個線程,桶AIDL與住線程通訊,根據業務須要適當的銷燬進程。

7)Cursor對象及時關閉

4 內存使用策略優化:

1)謹慎使用large heap,在一些特殊狀況下能夠經過mainfest的application 標籤添加largHeap=true來聲明一個更大heap空間,可是因爲總heap空間不變,會致使系統性能大打折扣。並且有的機器就不容許這樣的操做。

2)綜合考慮設備內存閥值與其餘因素,設計合適的緩存大小。

3)onLowMemory 與 onTrimMemory

4) 資源文件須要選擇合適的文件存放,不須要被拉伸的圖片須要放到assets活nodpi目錄下

5)try catch 某些大內存的分配操做,對於可能發生OOM的代碼,能夠考慮在catch裏面嘗試一次降級內存的操做。

6)謹慎使用static對象,由於static對象的生命週期過長。

7)特別留意單例對象中不合理的持有,由於單例的生命週期和應用保持一致,使用不合理容易致使對象泄露

8)儘可能使用IntentService,由於在它會處理完 任務後儘快結束本身。

9) 優化佈局層次,減小內存消耗

10)謹慎使用抽象編程,抽象編程可以提代碼的靈活些和可維護性,可是卻會形成一個顯著的額外內存消耗。

11)使用nano protobufs序列化數據,

12)謹慎使用依賴注入框架,雖然這個種方式簡化代碼,可是這些注入框架會經過掃描代碼執行屢次初始化操做,這樣會致使代碼須要大量的內存空間來mapping代碼,並且mapping pages會長時間保留在內存中。

13)謹慎使用多線程,使用多線程能夠把應用中的部分組件運行在單獨的進程中,擴大內存佔用範圍,可是必須謹慎使用,由於這個不經增長了代碼邏輯複雜性,使用不當並且會顯著增長內存,使用的前提是:須要運行一個常駐後臺,並且這個任務不是輕量級的,能夠考慮使用。

14)使用ProGuard提車不須要的代碼,減小mapping代碼須要的內存空間

15)謹慎使用第三方的libraries,特別是儘可能不要使用不是爲了移動網絡環境而編寫的。

16)考慮使用不一樣的方式優化內存佔用。

 

本文不是原創,只是做爲學習筆記記錄

相關文章
相關標籤/搜索