国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

常見內存泄漏分析

2019-11-09 18:44:59
字體:
來源:轉載
供稿:網友

1.確定是否存在內存泄露 1)Android Monitors的內存分析 最直觀的看內存增長情況,知道該動作是否發(fā)生內存泄露。 動作發(fā)生之前:GC完后內存1.4M; 動作發(fā)生之后:GC完后內存1.7M

2)使用MAT內存分析工具MAT分析heap的總內存占用大小來初步判斷是否存在泄露Heap視圖中有一個Type叫做data object,即數據對象,也就是我們的程序中大量存在的類類型的對象。在data object一行中有一列是“Total Size”,其值就是當前進程中所有java數據對象的內存總量,一般情況下,這個值的大小決定了是否會有內存泄漏。我們反復執(zhí)行某一個操作并同時執(zhí)行GC排除可以回收掉的內存,注意觀察data object的Total Size值,正常情況下Total Size值都會穩(wěn)定在一個有限的范圍內,也就是說由于程序中的的代碼良好,沒有造成對象不被垃圾回收的情況。反之如果代碼中存在沒有釋放對象引用的情況,隨著操作次數的增多Total Size的值會越來越大。

那么這里就已經初步判斷這個操作導致了內存泄露的情況。

2.先找懷疑對象(哪些對象屬于泄露的) MAT對比操作前后的hPRof來定位內存泄露是泄露了什么數據對象。(這樣做可以排除一些對象,不用后面去查看所有被引用的對象是否是嫌疑) 快速定位到操作前后所持有的對象哪些是增加了(GC后還是比之前多出來的對象就可能是泄露對象嫌疑犯) 技巧:Histogram中還可以對對象進行Group,比如選擇Group By Package更方便查看自己Package中的對象信息。

MAT分析hprof來定位內存泄露的原因所在。(哪個對象持有了上面懷疑出來的發(fā)生泄露的對象) 1)Dump出內存泄露“當時”的內存鏡像hprof,分析懷疑泄露的類; 2)把上面2得出的這些嫌疑犯一個一個排查個遍。步驟: (1)進入Histogram,過濾出某一個嫌疑對象類 (2)然后分析持有此類對象引用的外部對象(在該類上面點擊右鍵List Objects—>with incoming references) (3)再過濾掉一些弱引用、軟引用、虛引用,因為它們遲早可以被GC干掉不屬于內存泄露 (在類上面點擊右鍵Merge Shortest Paths to GC Roots—>exclude all phantom/weak/soft etc.references) (4)逐個分析每個對象的GC路徑是否正常 此時就要進入代碼分析此時這個對象的引用持有是否合理,這就要考經驗和體力了!

一般我是最笨的方法解決 new出來對象,用完后把它 = null;這樣算不算優(yōu)化 假如:方法里面定義的對象,要去管嗎?一般不需要管。 自己=null,要自己去控制所有對象的生命周期 判斷各種空指針,有點麻煩。 但是在很多時候去想到主動將對象置為null是很好的習慣。


判斷一個應用里面內存泄露避免得很好,怎么看? 當app退出的時候,這個進程里面所有的對象應該就都被回收了,尤其是很容易被泄露的(View,Activity)是否還內存當中。 可以讓app退出以后,查看系統(tǒng)該進程里面的所有的View、Activity對象是否為0. 工具:使用AndroidStudio–AndroidMonitor–System Information–Memory Usage查看Objects里面的views和Activity的數量是否為0. 命令行模式:

=========內存泄露經常出現的例子========== 內存泄露(Memory Leak): 進程中某些對象已經沒有使用價值了,但是他們卻還可以直接或者間接地被引用到GC Root導致無法回收。 當內存泄露過多的時候,再加上應用本身占用的內存,日積月累最終就會導致內存溢出OOM. 內存溢出(OOM): 當應用占用的heap資源超過了Dalvik虛擬機分配的內存就會內存溢出。比如:加載大圖片。

1.靜態(tài)變量引起的內存泄露 當調用getInstance時,如果傳入的context是Activity的context。只要這個單利沒有被釋放,那么這個 Activity也不會被釋放一直到進程退出才會釋放。 public class CommUtil { private static CommUtil instance; private Context context; private CommUtil(Context context){ this.context = context; }

public static CommUtil getInstance(Context mcontext){ if(instance == null){ instance = new CommUtil(mcontext); }// else{// instance.setContext(mcontext);// } return instance; }

2.非靜態(tài)內部類引起內存泄露 (包括匿名內部類) 錯誤的示范:

public void loadData(){//隱士持有MainActivity實例。MainActivity.this.a new Thread(new Runnable() { @Override public void run() { while(true){ try { //int b=a; Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }解決方案:將非靜態(tài)內部類修改為靜態(tài)內部類。(靜態(tài)內部類不會隱士持有外部類)

當使用軟引用或者弱引用的時候,MainActivity難道很容易或者可以被GC回收嗎?》 GC回收的機制是什么?當MainActivity不被任何的對象引用。 雖然Handler里面用的是軟引用/弱引用,但是并不意味著不存在其他的對象引用該MainActivity。 我連MainActivity都被回收了,那他里面的Handler還玩?zhèn)€屁。

3.不需要用的監(jiān)聽未移除會發(fā)生內存泄露 例子1: // tv.setOnClickListener();//監(jiān)聽執(zhí)行完回收對象 //add監(jiān)聽,放到集合里面 tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() { @Override public void onWindowFocusChanged(boolean b) { //監(jiān)聽view的加載,view加載出來的時候,計算他的寬高等。

//計算完后,一定要移除這個監(jiān)聽 tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this); } });例子2: SensorManager sensorManager = getSystemService(SENSOR_SERVICE); Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL); sensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST); //不需要用的時候記得移除監(jiān)聽 sensorManager.unregisterListener(listener);

4.資源未關閉引起的內存泄露情況 比如:BroadCastReceiver、Cursor、Bitmap、IO流、自定義屬性attribute attr.recycle()回收。 當不需要使用的時候,要記得及時釋放資源。否則就會內存泄露。

5.無限循環(huán)動畫 沒有在onDestroy中停止動畫,否則Activity就會變成泄露對象。 比如:輪播圖效果。


上一篇:LRUCache的實現原理

下一篇:基礎-6 fragment

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 舒城县| 襄樊市| 中山市| 独山县| 舟曲县| 清远市| 柯坪县| 阿坝| 乌海市| 永康市| 二手房| 于都县| 辽宁省| 京山县| 阜阳市| 颍上县| 增城市| 河东区| 花垣县| 卓资县| 靖安县| 石渠县| 柏乡县| 甘南县| 四川省| 北流市| 崇阳县| 游戏| 邢台县| 汝城县| 河西区| 蒙山县| 郎溪县| 黔东| 七台河市| 土默特右旗| 榆社县| 青州市| 宜丰县| 保亭| 岗巴县|