文章目錄
內存泄漏原理 : 長生命週期對象 , 持有短生命週期對象的引用 , 並且是強引用持有 , GC 無法釋放該短生命週期對象引用 , 造成 OOM ;
Android Profiler 工具參考官方文檔 : 使用 Memory Profiler 查看 Java 堆和內存分配
使用 Memory Analyzer ( MAT ) 內存分析工具分析內存快照 , 首先要將內存快照文件 , 轉化成 MAT 工具能識別的文件 , 然後使用 MAT 工具進行分析 ;
在博客 【Android 內存優化】Android Profiler 工具常用功能 ( 監測內存 | 內存快照 ) 中保存了內存快照文件 memory-20200625T145636.hprof , 要使用 MAT 工具分析該內存快照 , 需要先將該文件轉換成爲 MAT 標準的文件格式 ;
在博客 【Android 內存優化】使用 Memory Analyzer ( MAT ) 工具分析內存 ( hprof 文件轉換 | MAT 工具下載 | MAT 工具使用 ) 中轉換了 MAT 格式的內存快照 , 下載 Memory Analyzer ( MAT ) 內存分析工具 , 並在該工具中加載了 MAT 格式的文件 ;
本博客中開始在 Memory Analyzer ( MAT ) 內存分析工具 中分析內存快照 ;
一、 內存中最大的對象
內存中最大的對象 : Overview 中的餅圖中 , 列出了佔用最大內存的對象 ;
二、 查看每個類的對象實例的個數
1. 查看每個類的對象實例的個數 : 點擊 Histogram 直方圖 , 查看每個類實例個數 ;
2. Histogram 直方圖界面如下 : 其中列出了每個類對象個數 ;
三、 查看對象的引用與被引用
對象的引用與被引用 : 右鍵點擊某對象 , 選擇 List objects 選項 ;
① 查看該對象引用了哪些對象 : 選擇 with incoming reference 選項 ;
② 查看該對象被哪些對象引用 : 選擇 with outgoing reference 選項 ;
四、 查看對象到 GC Roots 的最短距離
1、 選擇 Merge Shortest Paths to GC Roots
查看對象到 GC Roots 的最短距離 : 在右鍵菜單中選擇 " Merge Shortest Paths to GC Roots " , 這裏就可以看到爲什麼對象可達性分析時 , 某些對象應該釋放 , 卻仍然存在與 GC Root 對象之間的引用鏈 ;
2、 GC Roots 與 GC 垃圾回收
存在與 GC Roots 引用鏈導致內存泄漏 : 該對象可能與 GC Root 對象不是直接引用 , 而是由其它對象簡介引用 , 導致存在這麼一條引用鏈 ;
具體的 GC 回收原理在 【Android 內存優化】Java 內存模型 ( Java 虛擬機內存模型 | 線程私有區 | 共享數據區 | 內存回收算法 | 引用計數 | 可達性分析 ) 博客中的可發行分析章節 , 有詳細的介紹 , 如果 GC Root 對象與某個對象之間有引用鏈 , 那麼該對象無法被 GC 回收 ;
3、 Merge Shortest Paths to GC Roots 各個選項簡介
Merge Shortest Paths to GC Roots 各個選項簡介 :
- with all reference : 列出所有的引用 ;
- exclude weak reference : 排除弱引用 ;
- exclude soft reference : 排除軟引用 ;
- exclude phantom reference : 排除虛引用 ;
- exclude weak/soft reference : 排除弱引用和軟引用 ;
- exclude all phantom/weak/soft etc. reference : 排除虛引用 , 弱引用 , 軟引用 ; 只查看強引用 ;
4、 查看對象強引用引用鏈
③ 查看強引用引用鏈 : 這裏選擇 exclude all phantom/weak/soft etc. reference 選項 , 只查看到 GC Roots 的強引用引用鏈 ;
該 AppCompatTextView 類有三個對象的引用鏈 :
- MainActivity 引用了 SurfaceView 對象
- SurfaceView 對象 中的引用了 ConstraintLayout 對象
- ConstraintLayout 對象 引用了 View 對象
- View 對象 引用了兩個 AppCompatTextView 對象
- ConstraintLayout 對象 引用了 View 對象
- SurfaceView 對象 中的引用了 ConstraintLayout 對象
- MainActivity 引用了 AppCompatDelegateImpl 對象
- AppCompatDelegateImpl 對象引用了 ActionBarOverlayLayout 對象
- ActionBarOverlayLayout 對象引用了 ActionBarContainer 對象
- ActionBarContainer 對象引用了 Toolbar 對象
- Toolbar 對象引用了 個 AppCompatTextView 對象
- ActionBarContainer 對象引用了 Toolbar 對象
- ActionBarOverlayLayout 對象引用了 ActionBarContainer 對象
- AppCompatDelegateImpl 對象引用了 ActionBarOverlayLayout 對象
這樣就找到了是哪個類引用了我們要查找的目標對象 , 然後在對應代碼中查找爲什麼沒有釋放這個類 ;