1. 程式人生 > >Android 記憶體溢位(OOM)問題分析方法

Android 記憶體溢位(OOM)問題分析方法

oom的原因? 1)物件設計不合理(單個物件的記憶體佔用過大、同類物件未重複利用); 2)一次性申請很大記憶體導致超出了系統對單個應用設定的記憶體上限(Dalvik Heap Size); 3)記憶體洩漏 如何利用工具定位oom? 1) 先查詢發生oom的是哪個activity? 可採取的查詢方式有:對每個activity使用adb shell dumpsys meminfo "process name",檢視哪個activity未被釋放;藉助heap viewer,手動GC,看哪個activiy的allocated size持續增長; 2) 開啟Android Monitor,操作1)中所定位的activity(多次開啟-關閉),生成hprof檔案。hprof檔案需要用sdk/platform-tools中的hprof-conv轉化後(終端輸命令提示hprof-conv“未找到命令”,可嘗試輸入hprof-conv的完整絕對路徑)再用MAT開啟,分析是哪個物件導致activity無法被釋放。
如何避免oom? 減小物件的記憶體佔用 1)使用輕量級的資料結構,例如儘量使用常量代替列舉型別(列舉型別是常量記憶體的2倍左右); 2)bitmap在decode時選擇合適的inSampleSize進行縮小; 3)xml儘量使用更小的圖片,否則有可能初始化時因記憶體不足引起InflationException; 記憶體物件的重複利用 1)ListView/GridView的getView中加入ConvertView的複用 2)Bitmap物件的複用(3級快取),避免重複申請物件 3)類似onDraw等頻繁呼叫的方法,一定需要注意避免在這裡做建立物件的操作,因為他會迅速增加記憶體的使用,而且很容易引起頻繁的gc,甚至是記憶體抖動。 4)對於大量的字串拼接的操作,使用StringBuilder來替代頻繁的“+”。 避免物件的記憶體洩露
1)內部類引用導致的洩漏(典型場景activity中Handler中有延遲的任務或者是等待執行的任務佇列過長,都有可能因為Handler繼續執行而導致Activity發生洩漏) 2)Activity Context被傳遞到其他例項中,這可能導致自身被引用而發生洩漏 3)監聽器和observer的登出 4)Cursor物件是否及時關閉 記憶體使用策略優化 1)考慮使用Application Context而不是Activity Context 2)資原始檔需要選擇合適的資料夾進行存放(例如xxhdpi的手機去引用hdpi目錄下的圖片會將其拉伸而顯著提高記憶體佔用) 3)Try catch某些大記憶體分配的操作(decode bitmap的時候,catch到OOM,可以嘗試把取樣比例再增加一倍之後,再次嘗試decode) 4)謹慎使用static物件,因其生命週期和整個應用程序一致 5)珍惜Services資源,後臺service在任務執行完畢後要及時停止,否則系統會傾向為了保留這個Service而一直保留Service所在的程序,導致該程序不能被回收。建議使用
IntentService
,它會在處理完交代給它的任務之後儘快結束自己。