參考以下博客 :
【Android 內存優化】Android Profiler 工具常用功能 ( 監測內存 | 內存快照 )
【Android 內存優化】使用 Memory Analyzer ( MAT ) 工具分析內存 ( hprof 文件轉換 | MAT 工具下載 | MAT 工具使用 )
【Android 內存優化】使用 Memory Analyzer ( MAT ) 工具分析內存 ( MAT 工具使用 | 最大對象 | 類實例個數 | 引用與被引用 | GC Roots 最短鏈 )
一、 報錯信息
啓動 Profiler 調試 Android 應用 , 點擊如下紅色選框中的按鈕 , 啓動後會自動開啓 Profiler 界面 ;
點擊 MEMORY 面板 , 即可進入 Memory 監控界面 , 在該界面中可以監控內存運行情況 ;
開始執行時運行平穩 , 內存一直保持在 97.4 MB 左右 ;
開啓某方法後 , 顯示某自定義組件 , 不斷循環繪製某多邊形 , 出現如下內存情況 :
二、 內存排查
點擊內存監控面板左上角的 Record 按鈕 , 錄製一段內容 , 然後進入如下界面 ;
一般情況下 , 不用多想 , 就是第一個類的對象內存泄漏 , 這裏的第一個類時 FinalizerReference 類 , 該對象創建了 5149 個 , 這裏泄漏的內存就是這個對象泄漏的 ;
點擊該對象 , 即可彈出右側對話框 , 顯示着創建的 5149 個對象的信息 ;
再次點擊右側的某個對象 , 打開該對象創建時的調用棧 , 查看究竟在什麼地方 , 創建了這麼多 FinalizerReference 對象 ;
發現是在一個自定義組件中 , 該組件的需求是根據用戶操作 , 實時顯示多邊形 , 多邊形基本是每隔 20ms , 就要重繪一次 , 這裏需要在 onDraw 方法中循環處理多邊形繪製 ;
三、 代碼分析及修改
點擊上面的調用棧最上層的方法 , 在循環裏出現不斷創建對象的方法 Path path = new Path() , 導致了內存泄漏 ;
private void draw(){
while(true){
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x1, y1);
path.lineTo(x2, y2);
path.close();
canvas.drawPath(path, paint);
}
}
修改方案 : 將創建對象語句移動到循環外部 , 在循環中只複用對象 , 這樣內存泄漏問題解決 ;
private void draw(){
Path path = new Path();
while(true){
path.reset();
path.moveTo(x, y);
path.lineTo(x1, y1);
path.lineTo(x2, y2);
path.close();
canvas.drawPath(path, paint);
}
}
總結 : 不要在循環裏創建對象 , 只能複用對象 , 或者使用已有的對象 ;
很小白的問題 , 找了好幾個小時 , 記錄下 , 吸取教訓 ;
四、 不同版本說明
上述 內存泄漏 在 Android 10 操作系統中沒有 , 在 Android 7 操作系統中出現 , 這個問題要注意 , 開發時要在不同版本的手機中進行內存性能優化測試 ;