日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 如何做一次内存泄漏大排查

發布時間:2024/9/30 Android 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 如何做一次内存泄漏大排查 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/112335970
本文出自【趙彥軍的博客】

文章目錄

    • 前言
    • 把內存泄漏的地方找出來
    • leakcanary 狀態
    • hprof
      • 如何獲取 HPROF
      • 如何打開 hprof 文件
    • Heap Dump
      • Heap Dump 是什么?
      • Heap Dump里面有什么?
    • 如何做一次 `Heap Dump` ?
    • 如何代碼觸發 Heap Dump
    • 如何手動觸發 GC
    • Android Profiler指標
    • Heap Dump指標分析
    • 對象跟蹤策略
    • 記錄某一段時間的內存分配情況
    • Memory Analyzer(MAT)
    • 祝福

前言

眼瞅著還有一個月就過年,項目也沒有那么忙了,技術老大要求做一做性能優化方面的工作。
而我的任務就是把項目中的內存泄漏擼一遍,然后安排對應的人處理。

說到內存泄漏,我也算是老手了,其實在 2016 年我就寫個內存泄漏方面的文章:

Android 如何有效的解決內存泄漏的問題

把內存泄漏的地方找出來

說干就干,首要的任務就是把內存泄漏的代碼揪出來,我選擇 leakcanary
github 地址:https://github.com/square/leakcanary/

關于 leakcanary 的介紹,集成步驟,我就不在這里展開講述了,網上有很多文章,你們自己搜索一下。

我只啰嗦一點:

  • 1、 leakcanary 2.0之后的版本集成不需要初始化

集成完成后,把項目跑起來,過一會就會報出來很多內存泄漏的日志。
在 Android Studio logcat 過濾 LeakCanary 就會看到如下:

同時在手機桌面也會有一個 小鳥圖標,點擊會看到可視化頁面

這里就可以看到內存泄漏的鏈條,分析的方式是 從下往上 的順序,比如針對本圖:

首先 MainActivity 實例發生內存泄漏 --> 再往上可以看到 MainActivity 泄漏 原因是 MainActivity 里的一個 Lambda 表達式引起的 --> … --> 再往上 看到 MutableLiveData 引起的 --> … --> …

看到這個分析鏈條,我們就很清楚了,大概率是 MutableLiveData 對象引起的,再結合實際的項目代碼,最后發現果然是因為 MainActivity 里的 MutableLiveData 對象沒有釋放。

特別要注意的是:

縱然 leakcanary 工具很牛逼,但是要想清晰的定位,然后修復內存泄漏,還是要結合實際的項目代碼的。

到這里我們基本就完成了 把內存泄漏揪出來 的問題。

leakcanary 狀態

在上面一部分,我貼了兩個圖,圖中的有很清晰的對象引用鏈條。leakcanary 對每個對象都標明了泄漏的狀態。

  • Leaking: YES 確定已經泄漏
  • Leaking: UNKNOWN 不確定是否泄漏
  • Leaking: NO 沒有泄漏

我們在分析 對象引用鏈條的時候,要特別注意 UNKNOWN 狀態,這個狀態即有可能是泄漏了,也有可能是沒有泄漏,這就需要我們程序要認真的分析項目代碼,然后給出結論

hprof

leakcanary 在運行的時候,發現內存泄漏了,會把 Java堆快照轉儲到Android HPROF文件中,方便開發者分析。

如何獲取 HPROF

方式一:通過 logcat 獲取

在 Android Studio 的 logcat 中會輸出 hprof 文件地址:


我們拿到 hprof 文件鏈接后,就可以通過 adb pull 命令導到電腦桌面

adb pull /storage/emulated/0/Download/leakcanary-com.cootek.crazyreader/2021-01-08_11-21-08_472.hprof ~/DeskTop

方式二:通過客戶端可視化頁面


點擊 Share Heap Dump file 可以通過分享出去。

正文到這里其實也就結束了。在做內存泄漏排查的時候用到了 AndroidStudio Profiler 工具,里面有很多新的概念和內存指標,下面的內容就是在探究 Profiler 工具如何使用以及各種內存指標所代表的含義

如何打開 hprof 文件

方式一:Android studio Profiler 功能打開

這個工具顯示了如下信息:

名稱描述
Class name類名
Total Count該類的實例總數
Heap Count所選擇的堆中該類的實例的數量
Sizeof單個實例所占空間大小(如果每個實例所占空間大小不一樣則顯示0)
Shallow Size堆里所有實例大小總和(Heap Count * Sizeof)
Retained Size該類所有實例所支配的內存大小
Instance具體的實例
Reference Tree所選實例的引用,以及指向該引用的引用。
DepthGC根節點到所選實例的最短路徑的深度
Shallow Size所選實例的大小
Dominating Size所選實例所支配的內存大小

用HPROF分析工具,可以檢測到泄漏的 Activity

通過這個可以看到 本次分析有 3 出泄漏的地方,點擊 第一個 ReaderActivity

可以看到詳細的泄漏實例,Depth 為 13 ,代表 GC根節點到所選ReaderActivity實例的最短路徑的深度是 13 。

Heap Dump

Heap Dump 是什么?

Heap Dump 也叫堆轉儲文件,是一個 Java 進程在某個時間點上的內存快照。Heap Dump 是有著多種類型的。不過總體上 heap dump 在觸發快照的時候都保存了 java對象和類的信息。通常在寫heap dump文件前會觸發一次FullGC,所以heap dump文件中保存的是FullGC后留下的對象信息。

簡單說就是:

heap dump文件是一個二進制文件,它保存了某一時刻JVM堆中對象使用情況。HeapDump文件是指定時刻的Java堆棧的快照,是一種鏡像文件。

Heap Dump里面有什么?

一般在 Heap Dump 文件中可以獲取到(這仍然取決于heap dump文件的類型)如下信息:

  • 對象信息:類、成員變量、引用值;
  • 類信息:類加載器、名稱、超類、靜態成員;
  • Garbage Collections Roots:JVM可達的對象;
  • 線程棧以及本地變量:獲取快照時的線程棧信息,以及局部變量的詳細信息

也就是說我們可以對上面這些內容進行分析。通??梢曰?Heap Dump 分析如下類型的問題:

  • 找出內存泄漏的原因;
  • 找出重復引用的jar或類;
  • 分析集合的使用;
  • 分析類加載器。

總而言之我們對 Heap Dump 的分析就是對應用的內存使用進行分析,從而更加合理地使用內存。

如何做一次 Heap Dump ?

在前面講到的,hprof 文件都是 Leakcanary 工具幫我們做的,那我們自己想要自己做一次 Heap Dump ,生成 hprof 文件又該怎么做呢?

其實 AndroidStudio 有現成的工具,只要動動手機就行了。

AndroidStudio --> Profiler --> 點擊 + 號 --> 選擇設備 --> 選擇進程 --> 點擊 MEMORY --> 點擊 向下的箭頭


由于生成的 hprof 文件比較大,所以解析出來比較慢,要耐心等待。

至此,我們就完成手動 Heap Dump 操作,并且生成 hprof 文件 。我們也可以點擊保存按鈕,把 hprof 文件保存到桌面,或者發給其他人。

如何代碼觸發 Heap Dump

代碼其實很簡單:

try {//指定Hprof文件的名字var path: String =externalCacheDir?.absolutePath + File.separator + System.currentTimeMillis() + ".hprof"Debug.dumpHprofData(path) } catch (e: Exception) {}

生成的文件在 Android/data/app包名/cache/ 目錄下:

如何手動觸發 GC

AndroidStudio --> Profiler --> 點擊 + 號 --> 選擇設備 --> 選擇進程 --> 點擊 MEMORY --> 點擊 像垃圾桶 的圖標


其實最快速的是點擊 右鍵

Android Profiler指標

官方文檔:https://developer.android.com/studio/profile/memory-profiler


內存計數中的類別如下:

  • Java:從 Java 或 Kotlin 代碼分配的對象的內存。

  • Native:從 C 或 C++ 代碼分配的對象的內存。

    即使您的應用中不使用 C++,您也可能會看到此處使用了一些原生內存,因為即使您編寫的代碼采用 Java 或 Kotlin 語言,Android 框架仍使用原生內存代表您處理各種任務,如處理圖像資源和其他圖形。

  • Graphics:圖形緩沖區隊列為向屏幕顯示像素(包括 GL 表面、GL紋理等等)所使用的內存。(請注意,這是與 CPU 共享的內存,不是 GPU專用內存。)

  • Stack:您的應用中的原生堆棧和 Java 堆棧使用的內存。這通常與您的應用運行多少線程有關。

  • Code:您的應用用于處理代碼和資源(如 dex 字節碼、經過優化或編譯的 dex 代碼、.so 庫和字體)的內存。

  • Others:您的應用使用的系統不確定如何分類的內存。

  • Allocated:您的應用分配的 Java/Kotlin對象數。此數字沒有計入 C 或 C++ 中分配的對象。

    如果連接到搭載 Android 7.1 及更低版本的設備,只有在內存性能分析器連接到您運行的應用時,才開始此分配計數。因此,您開始分析之前分配的任何對象都不會被計入。但是,Android 8.0 及更高版本附帶一個設備內置性能剖析工具,該工具可跟蹤所有分配,因此,在 Android 8.0 及更高版本上,此數字始終表示您的應用中待處理的 Java 對象總數。

Heap Dump指標分析

只有看懂了每個指標,才能更好的分析內存,下面我們分析一下 heap Dump 指標

對象跟蹤策略

為了在分析時提高應用性能,內存性能分析器在默認情況下會定期對內存分配進行采樣。在運行 API 級別 26 或更高級別的設備上進行測試時,您可以使用 Allocation Tracking 下拉菜單更改此行為??捎眠x項如下:

  • Full:捕獲內存中的所有對象分配。這是 Android Studio 3.2 及更低版本中的默認行為。如果您有一個分配了大量對象的應用,可能會在分析時觀察到應用的運行速度明顯減慢。
  • Sampled:定期對內存中的對象分配進行采樣。這是默認選項,在分析時對應用性能的影響較小。在短時間內分配大量對象的應用仍可能會表現出明顯的速度減慢。
  • Off/None:停止跟蹤應用的內存分配。

記錄某一段時間的內存分配情況

Heap Dump 是一個很好用的工具,能夠分析內存中所有的對象,但是也是有弊端的,Heap Dump 是全量分析,如果你想分析某一段時間內的內存增量分配情況,該怎么做呢?點擊 Record 按鈕.


下面用一個 gif 看看

Memory Analyzer(MAT)

Memory Analyzer 工具,簡稱:MAT 。

MAT 是 Eclipse 下的一個軟件,專門用來分析 Java內存堆。

官方下載地址:https://www.eclipse.org/mat/

安裝完成后,圖標如下

不得不說,這個工具長得很丑。

MAT可以打開 .hprof , 但是從 AndroidStudio 里面的導出的 .hprof 文件,MAT 是不支持查看的,所以需要轉化一下,Android SDK 自帶了轉化工具。

您可以使用 android_sdk/platform-tools/ 目錄中提供的 hprof-conv工具執行此操作。運行包含兩個參數(即原始 HPROF 文件和轉換后 HPROF 文件的寫入位置)的hprof-conv 命令。例如:

hprof-conv heap-original.hprof heap-converted.hprof

經過轉化過的 .hprof 文件,MAT 就可以打開了。

祝福

快過年了,祝大家 2021 事事順心,萬事大吉。新年快樂鴨 !!

總結

以上是生活随笔為你收集整理的Android 如何做一次内存泄漏大排查的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。