Android内存优化(四)解析Memory Monitor、Allocation Tracker和Heap Dump
相关文章
Android性能优化系列
Java虚拟机系列
前言
要想做好内存优化工作,就要掌握两大部分的知识,一部分是知道并理解内存优化相关的原理,另一部分就是善于运用内存分析的工具。本篇就来介绍内存分析工具:Memory Monitor、Allocation Tracker和Heap Dump的使用方法。
1.Memory Monitor
在Android Studio(以下简称AS)中Android Monitor是一个主窗口,它包含了Logcat,、Memory Monitor、CPU Monitor、 GPU Monitor和Network Monitor。其中Memory Monitor可以轻松地监视应用程序的性能和内存使用情况,以便于找到被分配的对象,定位内存泄漏,并跟踪连接设备中正在使用的内存数量。Memory Monitor可以报告出你的应用程序的内存分配情况, 更形象的呈现出应用程序使用的内存。它的作用如下:
- 实时显示可用的和分配的Java内存的图表。
- 实时显示垃圾收集(GC)事件。
- 启动垃圾收集事件。
- 快速测试应用程序的缓慢是否与过度的垃圾收集事件有关。
- 快速测试应用程序崩溃是否与内存耗尽有关。
1.1 使用Memory Monitor
在使用Memory Monitor之前要确保手机开启了开发者模式和USB调试。
使用的步骤为:
1.运行需要监控的应用程序。
2.点击AS面板下面的Android图标,并选择Monitors选项。
如果Memory Monitor已经运行,效果如下图所示(AS版本2.3.2)。
图中的标注的功能如下:
- Initiate GC(标识1):用来手动触发GC。
- Dump Java heap(标识2):保存内存快照。
- Start/Stop Allocation Tracking(标识3):打开Allocation Tracker工具(后面会介绍)。
- Free(标识4):当前应用未分配的内存大小。
- Allocated(标识5):当前应用分配的内存大小。
图中y轴显示当前应用的分配的内存和未分配的内存大小;x轴表示经过的时间。
1.2 大内存申请与GC
从上图可以看出,分配的内存急剧上升,这就是大内存分配的场景,我们要判断这是否是合理的分配的内存,是Bitmap还是其他的大数据,并且对这种大数据进行优化,减少内存开销。
接下来分配的内存出现急剧下降,这表示垃圾收集事件,用来释放内存。
1.3 内存抖动
内存抖动一般指在很短的时间内发生了多次内存分配和释放,严重的内存抖动还会导致应用程序卡顿。内存抖动出现原因主要是短时间频繁的创建对象(可能在循环中创建对象),内存为了应对这种情况,也会频繁的进行GC,因此综合起来就产生了内存抖动,产生了如上图般的锯齿状。
2.Allocation Tracker
Allocation Tracker用来跟踪内存分配,它允许你在执行某些操作的同时监视在何处分配对象,了解这些分配使你能够调整与这些操作相关的方法调用,以优化应用程序性能和内存使用。
Allocation Tracker能够做到如下的事情:
- 显示代码分配对象类型、大小、分配线程和堆栈跟踪的时间和位置。
- 通过重复的分配/释放模式帮助识别内存变化。
- 当与 HPROF Viewer结合使用时,可以帮助你跟踪内存泄漏。例如,如果你在堆上看到一个bitmap对象,你可以使用Allocation Tracker来找到其分配的位置。
2.1 使用Allocation Tracker
AS和DDMS中都有Allocation Tracker,这里会·介绍AS中的Allocation Tracke如何使用。首先要确保要确保手机开启了开发者模式,并且开启了USB调试。
使用的步骤为:
1.运行需要监控的应用程序。
2.点击AS面板下面的Android图标,并选择Monitors选项。
3.点击Start Allocation Tracking按钮,这时Start Allocation Tracking按钮变为了Stop Allocation Tracking按钮。
4.操作应用程序。
5.点击Stop Allocation Tracking按钮,结束快照。这时Memory Monitor会显示出捕获快照的期间,如下图所示。
6.过几秒后就会自动打开一个窗口,显示当前生成的alloc文件的内存数据。
2.2 alloc文件分析
自动打开的alloc文件窗口如下图所示。
该alloc文件显示以下信息:
列 | 说明 |
---|---|
Method | 负责分配的Java方法 |
Count | 分配的实例总数 |
Total Size | 分配内存的总字节数 |
接着我们来分析标红框的内容,负责分配的Java方法为performLaunchActivity,内存分配序列为2369,分配的对象为ActivityThread,分配的实例总数为300个,分配内存的总字节数为10512。不了解performLaunchActivity方法和ActivityThread可以看Android深入四大组件这一系列的文章。
目前的菜单选项是Group by Method我们也可以选择 Group By Allocator,如下图所示。
为了更好的解释图中的信息,这里给出测试的代码,MainActivity和SecondActivity 的代码如下所示。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button =(Button)findViewById(R.id.bt_next);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
}
SecondActivity.java
public class SecondActivity extends AppCompatActivity {
private static Object inner;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.bt_next);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createInnerClass();
finish();
}
});
}
void createInnerClass() {
class InnerClass {
}
inner = new InnerClass();
}
}
其中SecondActivity是存在内存泄漏的,生成快照期间,我的操作就是在MainActivity和SecondActivity跳转了3次(点击button 共6次)。这时我们回过头来看上图的红框的信息,MainActivity总共分配了3个Intent实例,占用内存为192字节。SecondActivity总共分配了6个实例,占用内存为96字节,其中分配了3个匿名内部类OnClickListener的实例,3个InnerClass的实例。
我们可以选择列表中的一项,单击鼠标右键,在弹出的菜单中选择jump to the source就可以跳转到对应的源文件中。
除此之外,还可以点击Show/Hide Chart按钮来显示数据的图形化,如下图所示。
3.Heap Dump
Heap Dump的主要功能就是查看不同的数据类型在内存中的使用情况。它可以帮助你找到大对象,也可以通过数据的变化发现内存泄漏。
3.1 使用Heap Dump
打开Android Device Monitor工具,在左边Devices列表中选择要查看的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体),在右边选择Heap选项,并点击Cause GC按钮,就会开始显示数据。我们每次点击Cause GC按钮都会强制应用程序进行垃圾回收,并将清理后的数据显示在Heap工具中。如下图所示。
从上图可以看出,Heap工具共有三个区域,分别是总览视图(标识1)、详情视图(标识2)和内存分配柱状图(标识2)。
3.2 总览视图
其中总览视图可以查看整体的内存情况,表中的显示信息如下所示。
列 | 说明 |
---|---|
Heap Size | 堆栈分配给该应用程序的内存大小 |
Allocated | 已分配使用的内存大小 |
Free | 空闲的内存大小 |
%Used | 当前Heap的使用率(Allocated/Heap Size) |
Objects | 对象的数量 |
结合上表和上图,我们在总览视图获得的信息就是:堆栈分配给当前的应用程序的内存大小为2.346MB,已分配的内存为1.346MB,空闲的内存为1MB,当前Heap的使用率为57.37%,对象的数量为24058个。
3.3 详情视图
详细视图展示了所有的数据类型的内存情况,表中列的信息如下所示。
列 | 说明 |
---|---|
Type | 数据类型 |
Total Size | 总共占用的内存大小 |
Smallest | 将该数据类型的对象从小到大排列,排在第一个的对象所占用的内存 |
Largest | 将该数据类型的对象从小到大排列,排在最后一个的对象所占用的内存 |
Median | 将该数据类型的对象从小到大排列,排在中间的对象所占用的内存 |
Average | 该数据类型的对象所占用内存的平均值 |
除了列的信息,还有行信息:
行 | 说明 |
---|---|
free | 内存碎片 |
data object | 对象 |
class object | 类 |
1-byte array (byte[],boolean[]) | 1字节的数组对象 |
2-byte array (short[],char[]) | 2字节的数组对象 |
4-byte array (object[],int[],float[]) | 4字节的数组对象 |
6-byte array (long[],double[]) | 8字节的数组对象 |
non-Java object | 非Java对象 |
行信息中比较重要的是free,它与总览视图中的free的含义不同,它代表内存碎片。当新创建一个对象时,如果碎片内存能容下该对象,则复用碎片内存,否则就会从free空间(总览视图中的free)重新划分内存给这个新对象。free是判断内存碎片化程度的一个重要的指标。
此外,1-byte array这一行的信息也很重要,因为图片是以byte[]的形式存储在内存中的,如果1-byte array一行的数据过大,则需要检查图片的内存管理了。
3.4 检测内存泄漏
Heap Dump也可以检测内存泄漏。在左边Devices列表中选择要查看的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体),在右边选择Heap选项,并点击Cause GC按钮,就会开始显示数据,如下图所示。
这时data object的Total Size为270.266KB。接下来操作应用,这个应用仍旧是在2.2小节所举的内存泄漏的例子,我反复的在MainActivity和SecondActivity跳转了10次(点击Button共20次),数据显示为:
data object的Total Size变为了768.172KB。这时我点击Cause GC按钮,数据显示为:
可以看到data object的Total Size变为了444.516KB,再点击一次Cause GC按钮:
Total Size变为了323.312KB,经过两次Cause GC的操作,Total Size的值从768.172KB变为了323.312KB,这是一个比较大的变化,说明在Cause GC操作之前有462.86KB(768.172KB-323.312KB)的内存没有被回收,可能发生了内存泄漏。
参考资料
Memory Monitor
Allocation Tracker
Android Monitor Basics
Android性能专项测试之Memory Monitor工具
《Android应用性能优化最佳实践》
《Android群英传 神兵利器》
《高性能Android应用开发》
Android内存优化(四)解析Memory Monitor、Allocation Tracker和Heap Dump的更多相关文章
- Android内存优化(二)解析Memory Monitor、Allocation Tracker和Heap Dump
前言 要想做好内存优化工作,就要掌握两大部分的知识,一部分是知道并理解内存优化相关的原理,另一部分就是善于运用内存分析的工具.本篇就来介绍内存分析工具:Memory Monitor.Allocatio ...
- Android 性能优化(23)*性能工具之「Heap Viewer, Memory Monitor, Allocation Tracker」Memory Profilers
Memory Profilers In this document Memory Monitor Heap Viewer Allocation Tracker You should also read ...
- Android内存优化7 内存检测工具1 Memory Monitor检测内存泄露
上篇说了一些性能优化的理论部分,主要是回顾一下,有了理论,小平同志又讲了,实践是检验真理的唯一标准,对于内存泄露的问题,现在通过Android Studio自带工具Memory Monitor 检测出 ...
- 【腾讯Bugly干货分享】Android内存优化总结&实践
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智 ...
- Android内存优化(三)详解内存分析工具MAT
前言 在这个系列的前四篇文章中,我分别介绍了DVM.ART.内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT. 1.概述 在进行内存分析时,我们可以使用M ...
- Android内存优化(一)DVM和ART原理初探
相关文章 Android内存优化系列 Java虚拟机系列 前言 要学习Android的内存优化,首先要了解Java虚拟机,此前我用了多篇文章来介绍Java虚拟机的知识,就是为了这个系列做铺垫.在And ...
- Android内存优化杂谈
Android内存优化是我们性能优化工作中比较重要的一环,这里其实主要包括两方面的工作: 优化RAM,即降低运行时内存.这里的目的是防止程序发生OOM异常,以及降低程序由于内存过大被LMK机制杀死的概 ...
- ANDROID内存优化——大汇总(转)
原文作者博客:转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! ANDROID内存优化(大汇总——上) 写在最前: 本文的思路主要借鉴了20 ...
- Android内存优化1 了解java内存分配 1
开篇废话 今天我们一起来学习JVM的内存分配,主要目的是为我们Android内存优化打下基础. 一直在想以什么样的方式来呈现这个知识点才能让我们易于理解,最终决定使用方法为:图解+源代码分析. 欢迎访 ...
随机推荐
- spring MVC Action里面怎么设置UTF-8编码集
/* 编码转换,确保写数据库的时候不会出现乱码 */ public class CodingConvert{ public CodingConvert(){ // } public String to ...
- Xcode8编辑代码崩溃解决办法
更新了Xcode8带来了一系列问题,最大的困扰就是不支持插件了,而且最关键的是一敲代码就崩溃(就是写一个字母就开始崩),在网上找了很多解决,发现是之前装的插件遗留下来的问题,将插件全部删掉就解决了,下 ...
- Oracle18c创建不带C##的用户
18c数据库分两种数据库CDB(容器数据库).PDB(可插拔数据库) 数据库安装完成之后,默认是CDB 创建一个用户,必须要用C##开头,但使用PDB没有这个限制 1. 先查看PDB数据库servic ...
- Spring Boot 中yml配置文件
步骤一:yml格式 现在大家发现,在springboot里还是要用到配置文件的. 除了使用.properties外,springboot还支持 yml格式. 个人觉得yml格式的可读性和..prope ...
- Spark(一)介绍
随着对spark的业务更深入,对spark的了解也越多,然而目前还处于知道的越多,不知道的更多阶段,当然这也是成长最快的阶段.这篇文章用作总结最近收集及理解的spark相关概念及其关系. 名词 dri ...
- 2017 beijing icpc A - Euler theorem
2017-09-22 21:59:43 writer:pprp HazelFan is given two positive integers a,ba,b, and he wants to calc ...
- Vjudge - F - 比前面更简单的模拟
2017-07-16 07:31:35 writer:pprp 题目介绍:很基础的string用法 题目如下: 读入一个字符串,字符串中包含ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出,当某个字 ...
- Web前端可以转行做游戏吗?
作者:ManfredHu 链接:http://www.manfredhu.com/2018/03/15/31-laya-game-tips/index.html 声明:版权所有,转载请保留本段信息,谢 ...
- [小问题笔记(八)] 常用SQL(读字段名,改字段名,打印影响行数,添加默认值,查找存储过程等)
读取所有字段,自然排序 declare @fields varchar(max) Select @fields=ISNULL(@fields,'')++name+',' from syscolumns ...
- 手把手教你整合 SpringMvc+Spring+MyBatis+Maven
注:该教程是参考孙宇老师的<SpringMvc+Spring+Mybatis+Maven整合视频教程1>整理的,花了我六个多小时,边复习视频边调代码边写教程,保证该教程每一步都能正确执行, ...