【錯誤記錄】Android 內存泄漏 錯誤排查記錄 ( FinalizerReference 內存泄漏 )



參考以下博客 :

【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 操作系統中出現 , 這個問題要注意 , 開發時要在不同版本的手機中進行內存性能優化測試 ;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章