内存泄漏的检测

检测内存泄漏的方法

1、Android device monitor --> memory
2、MAT(Memory Analyzer Tools):MAT下载地址
3、LeakCanary

强烈推荐:
Android Studio和MAT结合使用来分析内存问题

new Thread() :每次进入界面都会创建实例,并且不会被GC
非静态内存类的静态变量:只在第一次进入界面创建实例,并且不会被GC

Shallow Size

是对象本身占据的内存的大小,不包含其引用的对象。对于常规对象(非数组)的Shallow Size由其成员变量的数量和类型来定,而数组的ShallowSize由数组类型和数组长度来决定,它为数组元素大小的总和。

Retained Size

Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象

GC Root

JAVA虚拟机通过可达性(Reachability)来判断对象是否存活,
基本思想:以”GC Roots”的对象作为起始点向下搜索,搜索形成的路径称为引用链,
当一个对象到GC Roots没有任何引用链相连(即不可达的),则该对象被判定为可以被回收的对象,反之不能被回收。

GC Roots可以是以下任意对象

一个在current thread(当前线程)的call stack(调用栈)上的对象(例如方法参数和局部变量)
线程自身或者system class loader(系统类加载器)加载的类
native code(本地代码)保留的活动对象

Shallow Size、Retained Size、GC Root三者关系:

(1)只有强引用的对象(比如集合类型),在其对象中不断引用其他对象,这样才会导致memory leak.弱引用的对象会被GC回收从而不会导致memory leak.
(2)对于一个不引用其他自定义类对象的对象,它的Shallow Heap大小和Retained Heap大小相等,并且这个大小为这个对象的对象头(取决于平台是32位还是64位) 和所有成员变量的按照类型计算出的大小(如果是对象引用就是4个byte或者8个byte,也取决于平台是32位还是64位,这决定了你寻址用的地址的尺寸)的总和,并且做补位操作。
(3)对于一个引用其他自定义类对象的对象,它的Shallow Heap大小和Retained Heap大小不相等,Retained Heap尺寸为该对象自己的Shallow Heap大小加上它所有直接或者间接引用到的对象的大小的总和(不包括被GC Root直接间接引用的对象)

参考:通过分析Heap Dump 来了解 Memory Leak ,Retained Heap,Shallow Heap
Java堆:Shallow Size和Retained Size

内存泄漏

对于 C++ 来说,内存泄漏就是new出来的对象没有 delete,俗称野指针; 而对于 java 来说,就是 new 出来的 Object 放在 Heap 上无法被GC回收。

java的内存分配

静态存储区:编译时就分配好,在程序整个运行期间都存在。它主要存放静态数据和常量;

栈区:当方法执行时,会在栈区内存中创建方法体内部的局部变量,方法结束后自动释放内存;

堆区:通常用来存放new出来的对象。由java垃圾回收期回收。

在这里插入图片描述

四种引用类型的介绍

强引用(StrongReference):JVM 宁可抛出 OOM ,也不会让 GC 回收具有强引用的对象;

软引用(SoftReference):只有在内存空间不足时,才会被回的对象;

弱引用(WeakReference):在 GC 时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存;

虚引用(PhantomReference):任何时候都可以被GC回收,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否存在该对象的虚引用,来了解这个对象是否将要被回收。可以用来作为GC回收Object的标志。

参考:
Android性能优化第(二)篇—Memory Monitor检测内存泄露
Android性能优化第(三)篇—MAT比Menmery Monitor更强大
Android性能优化第(四)篇—Android渲染机制
Android性能专项测试

一、Android device monitor --> memory的使用:

这里写图片描述

坐标系:

y轴:内存
x轴:时间

灰色区域:空闲的内存(未分配的内存)
蓝色区域:分配的内存(当前正在使用中的内存总量)

按钮:

enabled:
启动与关闭Memory监测按钮:

在这里插入图片描述

initiate GC:
小汽车,代表GC按钮 ,可以手动GC,回收程序垃圾

在这里插入图片描述

Dump Java Heap:
向下的箭头,代表内存快照 ,点击可以生成一个文件(包名+日期+“.hprof”),可以记录某一个时间点内,程序内存的情况

在这里插入图片描述

Start/stop Allocation Tracking :
按钮先点击一次,然后会看到Memory Recorder开始转动,然后自己开始在APP上面做相应的操作。在合适的时间再点一次,结束记录。 
记录这段时间内的内存情况,也可以可以生成一个文件(包名+日期+“.alloc”)。

help:
帮助

AndroidStudio Memory使用流程:

1,运行要监控的程序(APP)后,打开Android Monitor控制台窗口,可以看到Memory控制台。
2,点击Memory控制台上Enable按钮,Memory控制台开始显示正在运行时程序的Memory使用情况。
3,单击启动GC图标。虚拟机发起的第一个垃圾回收事件。因为通常情况下,虚拟机是不会执行GC操作的,我们手动地进行GC操作来检测程序的内存使用等 情况。
4,点击Dump Java Heap按钮,APP会Freeze住。大概几十秒后,就会进入读取hprof文件的界面了,
这个文件记录着我们应用程序内部的所有数据,可以通过MAT等工具查看分析。
5,点击Starg Allocation Tracking按钮。开始分配追踪,过一些时间后,点击Stop Allocation Tracking结束追踪的位置。
这样就截取了一段要分析的内存,等待几秒钟AndroidStudio会给我们打开一个Allocation视图,
这个视图数据主要分析各个线程中的方法所占用内存的大小,从而可以找到需要优化的地方。

分析:

这里写图片描述

选择查看方式:
Heap类型分为:
App Heap -- 当前App使用的Heap
Image Heap -- 磁盘上当前App的内存映射拷贝
Zygote Heap -- Zygote进程Heap(每个App进程都是从Zygote孵化出来的, 这部分基本是framework中的通用的类的Heap)
view类型分为:
Class List View -- 类列表方式
Package Tree View -- 根据包结构的树状显示

板块A:class name这一栏,这个应用中所有类的名字
版块B:instance这一栏,左边类的所有实例
板块C:reference tree这一栏,在选择B中的实例后,这个实例的引用树
版块D:analyzer tasks这一栏,可以检测内存泄漏的activity
A板块左上角列名解释
Class Name	类名,Heap中的所有Class
Total Count	内存中该类这个对象总共的数量,有的在栈中,有的在堆中
Heap Count	堆内存中这个类 对象的个数
Sizeof	每个该实例占用的内存大小
Shallow Size	所有该类的实例占用的内存大小
Retained Size	所有该类对象被释放掉,会释放多少内存

B板块右上角上角列名解释
Instance	该类的实例
Depth	深度, 从任一GC Root点到该实例的最短跳数
Dominating Size	该实例可支配的内存大小

这里写图片描述

二、Mat的使用:

这里写图片描述

这里写图片描述

准备工作:在Android studio中左侧capture找到要检测的文件,并转为标准格式。

1、用mat工具打开

2、选择直方图:

这里写图片描述

3、选择group by package:

这里写图片描述

这里写图片描述

4、找到要检测的类比如:mainactivity,右键依次选择List objects–>with incoming references

这里写图片描述

注意:Activity或View大于1个对象, 都有可能发生内存泄露.

5、选择一个,右键依次选择path to GC toots -->exclude all Phantom /Weak / Soft etc. references(即只选择强引用导致的内存泄漏)

这里写图片描述

可以看到thread对mainactivity的强引用导致了内存泄漏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值