Android之内存泄漏分析

目录

前言

一.分析工具

二.分析过程

 

三.重要选项含义介绍

Histogram和Dominator Tree,大多数时候用到的也是这两个点:

 Path to GC Roots

 

通过OQL查询empty并且未修改过的集合:

内存中最大的对象 :

 查看对象的引用与被引用

查看对象到 GC Roots 的最短距离

 

Merge Shortest Paths to GC Roots

 

四.这里以Histogram为例点进去看下:

五.MAT的查询选项

OQL(Object Query Language)

FROM部分

SELECT部分

WHERE部分

自定义查询选项集合

List Objects

Show objects by class

Merge Shortest Path To GC Roots

 

Java Basics

Java Collections

Immidiate Dominators

Show Retained Set

结果分组

计算retained heap

六.神器LeakCanary

七.案例分析

分析view泄漏

 

单例造成的Activity内存泄漏

参考文献:


前言

  • 只有强引用才会造成内存泄漏
  • 内存泄漏原理 : 长生命周期对象 , 持有短生命周期对象的引用 , 并且是强引用持有 , GC 无法释放该短生命周期对象引用 , 造成 OOM ;
  • Android Profiler 工具参考官方文档 : 使用 Memory Profiler 查看 Java 堆和内存分配

一.分析工具

MAT (Memory Analyzer Tool)


二.分析过程

  1. 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 被该对象引用的对象
     

如下图

这里写图片描述

 

  • 查看指定类的Immediate dominators

  • Collections fill ratio 集合填充率

  • Map Collision Ratio

这里写图片描述

 

检测每一个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 的强引用引用链

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值