添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
纯真的柑橘  ·  Visual Studio中编译.cu ...·  3 月前    · 

Memory Profiler Android Profiler 中的一个组件,Android Profiler是Android3.0用来替换之前Android Monitor的观察工具,主要用来观察 内存 网络 cpu温度

Memory Profiler 它能够让你识别出来 内存泄露 内存抖动 ,导致 应用卡顿 anr crash ,他可以给你展示一个内存使用的真实图表,让你知道当时内存使用情况,还能 强制内存回收 ,和 跟踪内存分配

为什么去观察应用内存使用情况

Memory Profiler是用来解决内存分配中产生抖动,导致应用卡顿、anr和crash问题,在A ndroid系统内存管理上 ,它是提供一套 内存回收机制 去回收无用的对象,

其实就是Dalvik虚拟机的垃圾回收器,当垃圾回收器启动回收机制的时候,其实会对应用的运行产生一点影响,但是这种影响来说一般是微乎其微的,觉察不到,但是如果你的内存分配比垃圾回收快很多,这种情况可能导致垃圾回收器回收内存不及时,从而导致应用出现卡顿的现象(其实是内存抖动所产生的影响),另外一个问题是内存泄露,内存的持续泄露可能导致内存溢出,从而app运行出现oom异常

Memory Profiler通过以下方面防止上面出现的问题

1.观察不必要的内存分配(这种内存分配导致效率降低)

2.Dump the java heap去观察指定时间对象在内存中的分配情况,若干次Dump能够帮助你发现内存泄露

3.测试极端的用户交互情况下的内存分配(比如狂点某个请求按钮),看看内存使用情况如何,是否出现内存抖动

1:强制内存回收

2:Dump the java heap

3:开始/停止记录内存分配情况

4:放大/缩小时间线

5:实时播放内存分配情况

6:发生一些事件的记录(如Activity跳转,事件的输入、屏幕的旋转)

7:使用的内存时间线

关于顶部的几种内存类型介绍

Java:java代码分配的内存

Native:c/c++代码分配的内存(有时候其实并没有使用c/c++代码,但还是会有Native的内存分配,因为Android Framework会去通过java代码访问一些需要使用Native的资源,如图像资源的Bitmap)

Graphics:图像缓存等,包括GL surfaces,GL textures等

Stack:栈内存(包括java和c/c++)

Code:代码的内存分配(例如代码,资源,libs等等)

Other:这个是系统都不知道什么类型的内存

Allocated:java分配的对象个数

如何观察对象分配情况

查看内存分配情况,也就是我们前面提到需要关注什么类型的对象被分配,分配了多大空间

1.在Class Name列看一下有没有异常分配的对象,个数很多,占用内存比较大,点击头部Class Name进行一个按字母排序操作,点击Class Name面板下面的类名可以看到instance View面板的详细对象信息

2.点击Instance View面板上的对象,可以看到调用栈信息和调用的线程

3.在Call Stack中点击可以跳转到实际的代码

以上是捕获一段时间的内存分配情况,如果想捕获一瞬间的内存分布需要用到heap dump

捕获一个heap dump

捕获一个heap dump观察某一个时间点的对象分配情况,注意之前介绍的是一个时间段,而这里是时间点。它有助于帮助我们分析内存泄露,比如当我们使用一段时间后

捕获了一个heap dump这个heap dump里面发现了并不应该存在的内存对象,这说明存在内存泄露了,通过一个 heap dump你可以看到以下内容

1.你的app分配了什么样的对象类型,每个类型分配了多少个和大小

2.使用了多少内存

3.每个对象在代码中的使用位置

4.对象分配的调用栈情况

捕获一个heap dump在工具栏中点击之前面板介绍中的按钮2,稍等一会变能够看到类似于之前内存分配的面板弹出

在图片中可以看到如下列

Class Name:类名

Alloc Count:对象个数

Native Size:c/c++层内存大小(byte)

Shallow Size:java层内存大小(bytes)

Retained Size:这个是这个类中所引用到的对象的总大小*该类对象的个数

当点击app heap下拉列表会出现3个选项

Defaule heap:

App heap:app中的堆内存

Zygote heap:这个按照官方的解释是来自安卓系统fork进程的地方产生的写数据备份

当点击Arrange by class下拉列表会出现3个选项

Arrange by class:根据类名进行分组

Arrange by package:根据包名进行分组

Arrange by callstack:根据调用栈进行分配(这个目前也不是太理解)

当我们点击其中一个类的时候会弹出一个新的instance View面板,如下图:

分析heap,按照以下步骤:

1.浏览Class Name列表,看看有没有大量的对象存在,并且这些对象你认为是不应该存在的,可能存在内存泄露的情况,点击类名可以看到详细的对象信息

2.在这个Instance View面板中,点击一个实例References面板就会显示出来,里面都是使用该Instance的Reference,点击箭头可以看到引用它的所有区域,点击鼠标右键可以选择 go to instance去看到引用该引用的引用,或者jump to source去看调用的源代码

另外heap dump也是可以保存成为HPROF文件的,点击如下按钮可保存起来,用于以后分析,或用其他工具分析

一般出现内存泄露的原因有:

1.长期引用到Activity,Context,View,Drawable的对象

2.非静态内部类,例如Runnable她可以引用到Activity的实例

3,一些长期的缓存

具体分析一下 如何使用Memory Profiler查找内存泄露

查找内存泄露有以下几个方式

1.一般排查内存泄露的方式是,启动应用,看一下当前内存使用多少,使用应用一段时间后,退回到应用首页,看看当前内存又是多少,进行一次heap dump看看结果,分析一下有没有可疑对象分配(比如说大量重复的Activity,同一类型的对象比较多,对象内存占用较大)

2.发现可疑点后,通过分析结果,可疑找到相应代码,找到代码当然也能找到使用代码的场景,例如Activity泄露,返回进行画面跳转(如果你的应用支持横竖屏切换的话,也可以反复旋转屏幕),然后强制gc回收,看看内存是否存在只增不减的情况

3.也可以使用allocation跟踪一段时间内存分配情况,拿出来分析

4.最后推荐一款leakcanary工具使用(具体可看 https://github.com/square/leakcanary

启动一个类似内存泄露的app,然后跑一段时间,进行了一次heap dump,结果如下

很明显发现一个可疑的类OutOfMemActivity,它存在多个实例,实际上在已知该app业务逻辑中是不应该会有这么多OutOfMemActivity实例的,于是点开他的Instance View

可疑点如红色箭头所指,因为外部类实例引用到Activity都是不正常的操作,这里Broadvast的实例引用到了Activity

点击跳转到源码,发现是内部类引用到外部类实例(Activity)的情况导致内存泄露