内存泄漏原理 : 长生命周期对象 , 持有短生命周期对象的引用 , 并且是强引用持有 , 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 的最短距离 : 在右键菜单中选择 " Merge Shortest Paths to GC Roots " , 这里就可以看到为什么对象可达性分析时 , 某些对象应该释放 , 却仍然存在与 GC Root 对象之间的引用链 ;
存在与 GC Roots 引用链导致内存泄漏 : 该对象可能与 GC Root 对象不是直接引用 , 而是由其它对象简介引用 , 导致存在这么一条引用链 ;
具体的 GC 回收原理在 【Android 内存优化】Java 内存模型 ( Java 虚拟机内存模型 | 线程私有区 | 共享数据区 | 内存回收算法 | 引用计数 | 可达性分析 ) 博客中的可发行分析章节 , 有详细的介绍 , 如果 GC Root 对象与某个对象之间有引用链 , 那么该对象无法被 GC 回收 ;
Merge Shortest Paths to GC Roots 各个选项简介 :
③ 查看强引用引用链 : 这里选择 exclude all phantom/weak/soft etc. reference 选项 , 只查看到 GC Roots 的强引用引用链 ;
该 AppCompatTextView 类有三个对象的引用链 :
这样就找到了是哪个类引用了我们要查找的目标对象 , 然后在对应代码中查找为什么没有释放这个类 ;