您当前的位置: 首页 >  android studio

ZhangJiQun&MXP

暂无认证

  • 1浏览

    0关注

    1187博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Android studio Memory Profiler简单使用

ZhangJiQun&MXP 发布时间:2019-07-31 14:31:08 ,浏览量:1

 

二、基本介绍  Memory Profiler是Android Profiler的一个组件, 用于帮助分析内存泄露和内存抖动的问题。  Memory Profiler的功能包括:  展示应用内存使用情况的实时图像、抓取内存的dump信息、强制垃圾回收及追踪内存分配。

2.1 开启步骤  打开Memory Profiler的步骤为:  1、 依次点击Android Studio的View → Tool Windows → Android Profiler,  或直接点击工具栏Android Profiler对应的图标;

2、 PC连接Android终端后,在Android Profiler对应的区域选择接的设备和需要监控的进程: 

3、 点击Android Profiler界面中MEMORY区域的任意位置,即可开启Memory Profiler,如下图所示: 

需要注意的是,如果PC连接Android 7.1以下的设备时,有些关键数据可能无法被Android Profiler统计,  此时Android Profiler会显示如下信息: 

这时我们需要依次点击Android Studio的Run → Edit Configurations → Profiling 按键,选中app后点击Enabled advanced profiling,   为了支持该功能,要求app对应的gradle版本必须在2.4以上。

2.2 界面介绍 

其中: 标注1对应的按键用于强制内存回收。

标注2对应的按键用于抓取进程内存的dump信息。

标注3对应的按键用于记录内存的分配信息(连接Android 7.1及以下才会有此按键)。  初次点击时,对应统计的开始时间点;再次点击时,对应统计的结束时间点。  进程在两个时间点之间的内存分配信息,将被Memory Profiler记录和分析。

标注4对应的区域用于缩放时间轴。

标注5对应的按键用于显示实时的内存数据。

标注6对应的区域用于记录事件发生的时间点及大致持续的时间(例如activity状态改变、用户操作界面等事件)。

标注7对应的区域用于显示内存使用情况对应的时间轴(与标注6结合,就可以看出各事件带来的内存变化情况)。  需要说明的是,标注7对应区域显示的内容包括:  不同类型内存占用情况对应的图像;  分配对象数量对应的短画线;  内存回收事件发生的时机。

2.3 统计的数据类型及含义  Memory Profiler主要根据Android系统提供的信息,  统计app独自占用内存,即不统计app与系统或其它app共有的内存。

Memory Profiler统计内存的种类如下图所示:    如上图所示,其中: Java表示Java代码或Kotlin代码分配的内存;

Native表示C或C++代码分配的内存(即使App没有native层,调用framework代码时,也有可能触发分配native内存);

Graphics表示图像相关缓存队列占用的内存;

Stack表示native和java占用的栈内存;

Code表示代码、资源文件、库文件等占用的内存;

Others表示无法明确分类的内存;

Allocated表示Java或Kotlin分配对象的数量(Android8.0以下时,仅统计Memory Profiler启动后,进程再分配的对象数量;  8.0以上时,由于系统内置了统计工具,Memory Profiler可以得到整个app启动后分配对象的数量)。

三、基本用法  对Memory Profiler有了基本的了解后,我们来看看它的基本用法。

3.1 查看内存分配情况  Memory Profiler可以查看两个时间点之间的内存分配情况,包括:  对象的类型、占用内存的大小、栈信息等。  连接8.0以上的设备时,Memory Profiler还可以显示对象被回收的时间。

PC连接8.0以上的设备时,在内存统计的时间线上,直接点击和拖动就可以选择观察区域;  连接低版本的设备时,则需要点击Record Memory allocations按键(2.2小结介绍的标注3)选择观察区域。

选定观察区域后, Memory Profiler就可以统计这段时间内app分配内存的情况:    从图中可以看出,Memory Profiler可以显示分配对象的类名;  点击类后,会在Instance View显示具体的对象;  点击具体对象后,会在Call back区域显示调用栈。  点击调用栈信息后,就会跳转到具体的代码。

3.2 查看内存占用情况  点击2.2小结介绍的标注2,即可抓取点击后一段时间内app占用内存的dump信息。

通过dump信息,我们可以看到app当前仍存在于内存中的对象。  结合代码,我们可以分析是否有本应被析构却仍存活的泄露对象。

与统计内存分配信息一样,内存占用信息同样会显示对象的类型、数量、占用内存的大小、引用关系等。  如下图所示:     图中Alloc Count表示堆中分配对象的数量;  Shallow Size表示对象使用Java内存的大小,单位为byte;  Retained Size表示对象占用的实际内存大小,大于等于Shallow Size;  7.0及以上版本的设备,还会显示对象占用的Native Size。

点击具体的对象时,也会显示Instance View。  此时,Instance View显示的信息变多了,包括:  Depth表示当前对象到任一GC root的最短跳数;  Shallow Size、Retained Size的含义与前文一致。  同样,7.0及以上版本的设备,还会显示对象占用的Native Size。

从图中可以看出,Instance View不会显示栈信息。  如果想获得栈信息的话,必须先点击Record Memory allocations按键。

四、使用示例  利用Memory Profiler,我分析了一下某反病毒引擎SDK的内存占用情况。  随便写了个demo,继承SDK后启动app,内存占用情况如下图所示:    然后,通过操作UI初始化SDK,发现稳定后内存占用情况如下图所示:     比对前后两图,不考虑界面UI变化消耗的内存,  可以看出:内存增加的主体部分来自于Native函数,其它类型的内存变化几乎可以忽略。  这是因为该SDK初始化时,最主要的工作是在Native层加载底层的so文件。

接下来,我们在demo里调用SDK的接口,批量扫描样本,统计内存消耗情况如下图所示:     从图中可以看出app消耗的内存飙升到了104M,  与初始化后的内存相比,其中增加主要是code和native类型的内存。

根据2.3小结的描述,我们知道code类型统计的是app进程需要的资源文件、库文件等,  因此这部分内存主要是SDK中引擎加载病毒库等消耗掉的内存;  而Native内存的消耗,应该也是由于引擎扫描文件导致的。

按照3.1小结的描述,我们查看了一下批量扫描这段时间内,  app进程内存分配的情况,如下图所示:     容易看出,在这段时间内,除去native内存外,整个app分配内存并不大,  且按照对象占用内存的大小排序,排在前列的都是基本数据类型。  因此,这段时间内app进程的内存应该是比较正常的。

我们进行GC操作,内存情况如下图所示:    发现内存几乎和扫描前一致,按照3.2小结进行dump分析,没有发现泄露对象。  因此,可以确认SDK不存在内存泄露的问题(dump信息含有sdk的隐私,这里就不再附图了)。

不同于LeakCanary,  Android Memory Profiler更侧重于宏观场景下的内存分析。  

关注
打赏
1665659684
查看更多评论
立即登录/注册

微信扫码登录

0.0428s