目录
Histogram和Dominator Tree,大多数时候用到的也是这两个点:
Merge Shortest Paths to GC Roots
Merge Shortest Path To GC Roots
前言
- 只有强引用才会造成内存泄漏
- 内存泄漏原理 : 长生命周期对象 , 持有短生命周期对象的引用 , 并且是强引用持有 , GC 无法释放该短生命周期对象引用 , 造成 OOM ;
- Android Profiler 工具参考官方文档 : 使用 Memory Profiler 查看 Java 堆和内存分配
一.分析工具
MAT (Memory Analyzer Tool)
二.分析过程
- dump 内存hprof文件
导出方法:
AndroidStuido
命令
DDMS
2. hprof 文件转换,转换为MAT可以识别的文件
hprof-conv 命令 :
hprof-conv -z srcFile dstFile
如下;
hprof-conv -z a.hprof b.hprof
① -z 命令选项 : 表示排除非 APP 内存的堆 , 如 Zygote 内存等 ;
② srcFile 参数 : -z 后第一个参数是 源文件 , 即从 Android Studio 中保存的内存快照文件 , memory-20200625T145636.hprof ;
③ dstFile 参数 : 后面的第二个参数是目标文件 , 即将转换后的结果保存到该文件中
3.使用MAT打开hprof文件
三.重要选项含义介绍
Histogram和Dominator Tree,大多数时候用到的也是这两个点:
1、Histogram:是针对对象的数量,可以这么理解,一个类可以创建多个对象,这里查看的就是一个类总共创建了多少个对象;
2、Dominator Tree: 支配树,是针对的对象引用关系,以及该类所有实例对象所占用内存的百分比;
可以直观地反映一个对象的retained heap,这里我们首先要了解两个概念,shallow heap和retained heap:
- shallow heap:指的是某一个对象所占内存大小。
- retained heap:指的是一个对象的retained set所包含对象所占内存的总大小。
retained heap值的计算方式是将Retained set中的所有对象大小叠加。或者说,由于X被释放,导致其它所有被释放对象(包括被递归释放的)所占的heap大小。
Retained Set 当X被回收时那些将被GC回收的对象集合。
比如: 一个ArrayList持有100,000个对象,每一个占用16 bytes,移除这些ArrayList可以释放16 x 100,000 + X,X代表ArrayList的shallow大小。相对于shallow heap,Retained Heap可以更精确的反映一个对象实际占用的大小(因为如果该对象释放,retained heap都可以被释放)
Path to GC Roots
选择exclude all phantom/weak/soft etc.references, 意思是查看排除虚引用/弱引用/软引用等的引用链
List objects with (以Dominator Tree的方式查看)
- incoming references 引用到该对象的对象
- outcoming references 被该对象引用的对象
- Show objects by class (以class的方式查看)
- incoming references 引用到该对象的对象
- outcoming references 被该对象引用的对象
如下图
检测每一个HashMap或者HashTable实例并按照碰撞率排序 碰撞率 = 碰撞的实体/Hash表中所有实体
当Hash集合中过多的对象返回相同Hash值的时候,会严重影响性能(Hash算法原理自行搜索),这里来查找导致Hash集合的碰撞率较高的罪魁祸首
HashEntries
通过查看key value
通过OQL查询empty并且未修改过的集合:
- select * from java.util.ArrayList where size=0 and modCount=0 类似的
- select * from java.util.HashMap where size=0 and modCount=0
- select * from java.util.Hashtable where count=0 and modCount=0
内存中最大的对象 :
Overview 中的饼图中 , 列出了占用最大内存的对象 ;
查看对象的引用与被引用
对象的引用与被引用 : 右键点击某对象 , 选择 List objects 选项 ;
① 查看该对象引用了哪些对象 : 选择 with incoming reference 选项 ;
② 查看该对象被哪些对象引用 : 选择 with outgoing reference 选项 ;
查看对象到 GC Roots 的最短距离
Merge Shortest Paths to GC Roots
查看对象到 GC Roots 的最短距离 : 在右键菜单中选择 " Merge Shortest Paths to GC Roots " , 这里就可以看到为什么对象可达性分析时 , 某些对象应该释放 , 却仍然存在与 GC Root 对象之间的引用链 ;
-
GC Roots 与 GC 垃圾回收
存在与 GC Roots 引用链导致内存泄漏 : 该对象可能与 GC Root 对象不是直接引用 , 而是由其它对象间接引用 , 导致存在这么一条引用链 ;
具体的 GC 回收原理在 【Android 内存优化】Java 内存模型 ( Java 虚拟机内存模型 | 线程私有区 | 共享数据区 | 内存回收算法 | 引用计数 | 可达性分析 ) 博客中的可发行分析章节 , 有详细的介绍 , 如果 GC Root 对象与某个对象之间有引用链 , 那么该对象无法被 GC 回收 ;
- 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 : 排除虚引用 , 弱引用 , 软引用 ; 只查看强引用 ;
- 查看对象强引用引用链
查看强引用引用链 : 这里选择 exclude all phantom/weak/soft etc. reference 选项 , 可查看到 GC Roots 的强引用引用链