Android 内存分析工具

2023-11-11



Dalvik 虚拟机支持垃圾收集,但是这不意味着你可以不用关心内存管理。你应该格外注意移动设备的内存使用,手机和平板的内存空间是受到限制的。

在这篇文章里面,我们来看看Android SDK里面的一些内存剖析工具(profiling tools)是如何帮助我们修整应用程序的内存使用。

一、 内存泄露

一些内存使用问题是很明显的,例如,如果在每次用户触摸屏幕的时候应用程序有内存泄露,将会有可能触发OutOfMemoryError,最终程序崩溃。

另外一些问题却很微妙,也许只是降低应用程序和整个系统的性能(当高频率和长时间地运行垃圾收集器的时候)。



二、 内存工具

Android SDK 提供了2个主要的剖析应用程序内存使用情况的工具:Allocation Tracker 和 heap dumps

1)Allocation Tracker是很有用的,特别是当你想得到程序在一定的时间里内存的分配情况的一种感性认识的时候。但是它不能给你任何关于程序heap总体情况的任何 信息。关于Allocation Tracker的更多信息,请看文章Tracking Memory Allocations 


2)heap dumps,它是更强大的内存分析工具,一个heap dump就是一个程序heap的快照,它保存为一种叫做HPROF的二进制格式。Dalvik用的也是类似的格式,但是不完全一样,这里是Java 的HPROF工具 。有很多方法去生成一个运行时应用程序的heap dump,其中一种就是使用在DDMS里边的Dump HPROF file按钮,如果想产生更精确的dump数据,可以在程序中使用android.os.Debug.dumpHprofData() 方法。

分析heap dump,你可以使用一些标准的工具比如 jhat 或者Eclipse MATMemory Analyzer Tool 。不过,首先需要把.hprof文件从Dalvik格式转换成J2SE HPROF格式,你可以使用Android SDK提供的hprof-conv工具。例如:

hprof-conv  dump.hprof  converted-dump.hprof  



三、 内存调试

Dalvik 运行时里,程序员不能显式地分配和释放内存,所以这里的内存泄露跟C和C++里面的不同。在你的代码里,内存泄露就是你保留了一个并不再需要的类对象的引用,有时候仅仅一个引用就会阻碍gc对一大堆对象的回收。

我们来过一个实际的例子,Android SDK里面提供的范例程序Honeycomb Gallery sample app 。它是一个photo gallery程序,用来演示一些新的Honeycomb API的使用。(下载和编译这些代码,请看这些 命令 )我们会有意地加入一个内存泄露在程序里边,然后来演示如何调试它。

想象一下我们想修改程序让它从网络下载图片,为了让它更具备灵活性,我们可以考虑实现一个缓存,保存最近查看过的图片,我们可以对ContentFragment.java做一些小的修改来达到这个目的。在class顶部,我们增加一个新的静态变量:

private   static  HashMap<String,Bitmap> sBitmapCache =  new  HashMap<String,Bitmap>();  

这里是我们保存缓存的地方,现在可以修改updateContentAndRecycleBitmap()方法,让它在下载之前先查看是否数据已经存在,如果不存在就去下载,然后添加数据到缓存。

  1. void updateContentAndRecycleBitmap (int category, int position) {  
  2.     if (mCurrentActionMode != null) {  
  3.         mCurrentActionMode.finish();  
  4.     }  
  5.   
  6.     // Get the bitmap that needs to be drawn and update the ImageView.  
  7.   
  8.     // Check if the Bitmap is already in the cache  
  9.     String bitmapId = "" + category + "." + position;  
  10.     mBitmap = sBitmapCache.get(bitmapId);  
  11.   
  12.     if (mBitmap == null) {  
  13.         // It's not in the cache, so load the Bitmap and add it to the cache.  
  14.         // DANGER! We add items to this cache without ever  removing any.  
  15.         mBitmap = Directory.getCategory(category).getEntry(position).getBitmap(getResources());  
  16.         sBitmapCache.put(bitmapId, mBitmap);  
  17.     }  
  18.       
  19.     ((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);  
  20. }  
	void updateContentAndRecycleBitmap (int category, int position) {
		if (mCurrentActionMode != null) {
			mCurrentActionMode.finish();
		}

		// Get the bitmap that needs to be drawn and update the ImageView.

		// Check if the Bitmap is already in the cache
		String bitmapId = "" + category + "." + position;
		mBitmap = sBitmapCache.get(bitmapId);

		if (mBitmap == null) {
			// It's not in the cache, so load the Bitmap and add it to the cache.
			// DANGER! We add items to this cache without ever  removing any.
			mBitmap = Directory.getCategory(category).getEntry(position).getBitmap(getResources());
			sBitmapCache.put(bitmapId, mBitmap);
		}
		
		((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);
	}

在这里故意引入了一个内存泄露的问题:我们把图片加入了缓存但是从来没有移除他们,在真实的应用里,我们可以会用某种方法来限制缓存的大小。

 


四、 DDMS检查heap

 Dalvik Debug Monitor Server(DDMS)是主要的Android调试工具之一,也是 ADT Plugin for Eclipse 的一部分,独立的程序版本也可以在Android SDK的根目录下的tools/下面找到。关于DDMS更多的信息,请参考使用DDMS 。

我们来使用DDMS检查这个应用的heap使用情况,你可以使用下面的两种方法启动DDMS:

  • from Eclipse: click Window —> Open Perspective —> Other... —> DDMS
  • from the command line: run ddms (or ./ddms on Mac/Linux) in the tools/ directory

在左边的面板,选择进程com.example.android.hcgallery,然后在工具条上边点击Show heap updates按钮。这个时候切换到DDMS的VM Heap分页,它会显示每次gc后heap内存的一些基本数据。

如果想查看第一次gc后的数据内容,点击Cause GC按钮:

我们可以看到现在的值(Allocated列)是有一些超过8MB。现在滑动相片,这时看到 数据在增大,因为只有仅仅13个相片在程序里边,所以泄露的内存只有这么大。在某种程度上来说,这是最坏的一种内存泄露,因为我们没法得到 OutOfMemoryError来提醒我们说现在内存溢出了。



五、 生成heap dump

为了使用heap dump来追踪这个问题,首先要保存HPROF文件:

点击DDMS工具条上面的Dump HPROF文件按钮,选择文件存储位置,然后在运行hprof-conv。在这个例子里我们使用独立的MAT版本(版本1.0.1),MAT下载 。

如果使用ADT(它包含DDMS的插件)同时也在eclipse里面安装了MAT,点击“dump HPROF”按钮将会自动地做转换(用hprof-conv),同时会在eclipse里面打开转换后的hprof文件(它其实用MAT打开)。

 


六、 MAT分析heap dumps

启动MAT,然后加载刚才我们生成的HPROF文件。

MAT是一个强大的工具,讲述它所有的特性超出了本文的范围,所以我只想演示一种你可以用来检测 泄露的方法:直方图(Histogram)视图。它显示了一个可以排序的类实例的列表,内容包括:shallow heap(所有实例的内存使用总和),或者retained heap(所有类实例被分配的内存总和,里面也包括他们所有引用的对象)。

如果我们按照shallow heap排序,我们可以看到byte[] 实例在顶端。自从Android 3.0(Honeycomb),Bitmap的像素数据被存储在byte数组里 (之前是被存储在Dalvik的heap里),所以基于这个对象的大小来判断,不用说它一定是我们泄露掉的bitmap。

 右击byte[] 类,然后选择List Objects —> with incoming references,它会生成一个heap上的所有byte数组的列表,在列表里我们可以按照Shallow Heap的使用情况来排序。

 选择并展开一个比较大的对象,它将展示从根到这个对象的路径 —— 就是一条保证对象有效的链条。注意看,这个就是我们的bitmap缓存!

 MAT 不会明确告诉我们这就是泄露,因为它也不知道这个东西是不是程序还需要的,只有程序员知道。

在这个案例里面,缓存使用的大量的内存会影响到后面的应用程序,所以我们可以考虑限制缓存的大小。

 


七、 MAT 比较两个heap dumps

 调试内存泄露时,有时候适时比较2个地方的heap状态是很有用的。这时你就需要生成2个单独的HPROF文件(不要忘了转换格式),下面是一些关于如何在MAT里比较2个heap dumps的内容(有一点复杂):

  1. 第一个HPROF 文件(using File —> Open Heap Dump )
  2. 打开 Histogram view 
  3. 在Navigation History view里 (如果看不到就从Window —> Navigation History找 ), 右击histogram然后选择Add to Compare Basket 
  4. 打开第二个HPROF 文件然后重做步骤2和3
  5. 切换到Compare Basket view,然后点击Compare the Results (视图右上角的红色"!"图标)。



八、 总结

这本篇文章里面,我展示了Allocation Tracker 和 heap dumps是如何给你一种对程序内存使用的感性认识。我也展示了MAT可以帮助追逐我们程序里面的内存泄露问题。

MAT是一个强大的工具,我也仅仅触碰了一些皮毛,如果你想学习更多内容,我建议读 一些下面的文章:

说明: 上面两个博客网址,可能被“墙”了,需要通过VPN 或 IPv6 + sixxs.org代理访问
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 内存分析工具 的相关文章

  • Win11家庭版完美解决旧版exe的DPI显示高清修复

    由于Win11家庭版的一些限制 不能直接按Win R搜索打开gpedit msc来执行相关操作 修改注册表对普通用户又太危险 因此本文介绍了一种更简便的操作方法 来设置旧程序对现在电脑的高DPI的适配 一共12个步骤 步骤1 打开 开始 搜
  • flutter 超详细的sqflite数据库使用详解

    前言 数据持久化存储是app开发过程中比较常见的需求 对于简单的配置数据我们可以通过SharedPreference来实现 但是如果是类似用户列表 商品列表等的大量复杂数据 再使用SharedPreference来存储就不合适了 本篇我们就
  • curl命令多行执行

    window环境执行 分割符是 curl http surge jdfmgt com core r coreAutoInitiateMain testAddData X POST d objectCreateCount 1 typeCode
  • leecode151 反转字符串中的单词(附有手写思路)

    丑陋的思路 StringJoiner版本 前言 刚开始我是用StringJoiner写的 因为我看到这个每个元素之间有一个固定的空格我就想着能够直接用这个StringJoiner来进行书写 但是我提交的时候说这个StringJoiner无法
  • leetcode分类刷题:哈希表(Hash Table)(三、循环存在问题)

    1 当需要快速判断某元素是否出现在序列中时 就要用到哈希表了 2 本文针对的总结题型为给定的序列或需要构造的序列中是否存在循环 与 160 相交链表 141 环形链表 142 环形链表 II的题型一样 202 快乐数 这道题还考察如何对正整
  • AndroidStudio内各个模拟器的安装位置

    As中 下载的本地模拟器的位置位于 android avd目录下 当该目录被删除后 打开AndroidStudio的AVD 会发现所有的下载过的模拟器都没有了
  • 【2021-04-07华为机试】第二题:各任务执行完毕需要的时间

    题目 给定N个任务 1 lt N lt 100 任务编号从0开始顺序累加 这N个任务在系统中排队顺序执行 每个任务的自身执行时间为非负整数 依次为t1 t2 tn 部分任务之间存在依赖关系的 某任务所依赖的任务如果没有执行 则该任务需要重回
  • IDEA 中设置自动补全方法

    最近转用 IDEA 但习惯于 Eclipse 的快捷键和快捷输入 以下是在 IDEA 中增添快捷键和快捷输入的方法 1 File Settings 2 Editor Live Templates Add Template Group gt
  • Ant Design Pro新增页面步骤

    新增页面步骤 根据页面结构规范创建页面文件后 接着在项目根目录寻找config文件夹下的routes js中添加该页面项的路由配置 如创建子路由则在父路由下定义routes属性 值为一个数组 数组中为该路由的子路由路由配置项 如下图 exp
  • 微信隐藏功能系列3:微信关闭朋友圈广告推送

    我们使用微信好多年了 这个工具不仅仅在社交上为我们带来许多好处 工作 消费中也是给我们带来不少方便之处 大家对微信隐藏功能了解多少 本期分享 微信关闭朋友圈广告推送 虽然微信为我们带来许多方便 但令人不适的东西也是有的 广告就是其中之一 特
  • python如何创建二维数组

    关于python中的二维数组 主要有list和numpy array两种 好吧 其实还有matrices 但它必须是2维的 而numpy arrays ndarrays 可以是多维的 两者可以相互转化 下边是两者区别 数组list gt g
  • linux va_start 编译,如何把unix 下的c程序移植到suse linux下,编译出错?

    FILE gfp out stdout 第45行 报 err c 45 error initializer element is not constant include int err set info char ps error typ
  • c++:STL容器及其接口(string、vector、deque、stack、queue、list、set/multiset、map/multimap)

    STL Standard Template Library 标准模板库 目录 一 STL 六大组件简介 二 string容器 2 1 string容器基本概念 2 2 string 构造函数 2 3 string基本赋值操作 2 4 str
  • 第五章可视化

    1散点图 1 代码 A 未处理异常值 import ggplot as gp import pandas as pd import numpy as np crime pd read csv crimeRatesByState2005 cs
  • git交互式暂存 git add -i 这个骚操作存在的意义为何

    文章目录 启用交互暂存 暂存常用的命令 交互暂存的意义在哪 应该场景的进一步说明 你已经能非常熟练的使用 git了 暂存是其中最基本的操作了 交互暂存是暂存的高级用法 虽然可以不用 但是在某些特定场景下 可以提高我们的工作效率 下边请看详细
  • Opencv3.1+python2.7的CentOS7安装

    time Jan 13 2016 20 29 author duanxxnj 163 com 花了两天时间才把Openv3 1的Python安装完成 中间遇到了好多奇怪的错误 在这里记录下整个安装过程 系统环境 Duanxx CentOS
  • js debugger的两种方式

    第一种 在js代码中加上debugger class ReactiveEffect constructor fn scheduler this fn fn this scheduler scheduler this active true
  • HDU - 6126 Give out candies

    Give out candies 题解 第一次遇见这样处理的网络流模型 将问题转换成最小割问题 具体的题解参考自 传送门 先将每个人的拆成m个人 然后s向第1人连边流量为inf 第i个人向第i 1个人连边 流量为 3000 w 将t视为每组

随机推荐

  • 自用IdeaVim配置

    具体配置如下 nnoremap
  • STL之set集合容器

    set集合容器实现了红黑树 Red Black Tree 的平衡二叉检索树的的数据结构 在插入元素时 它会自动调整二叉树的排列 把该元素放到适当的位置 以确保每个子树根节点的键值大于左子树所有节点的键值 而小于右子树所有节点的键值 另外 还
  • 校门外的树C语言详解

    题目描述 某校大门外长度为 l 的马路上有一排树 每两棵相邻的树之间的间隔都是 1 米 我们可以把马路看成一个数轴 马路的一端在数轴 0 的位置 另一端在 l 的位置 数轴上的每个整数点 即 0 1 2 l 都种有一棵树 由于马路上有一些区
  • 自动化办公:4、 Python操作PDF

    1 相关介绍 PyPDF2 读取 写入 分割 合并PDF文件 pdfplumber 读取 PDF 文件中内容和提取 PDF 中的表格 pip install PyPDF2 pip install pdfplumber 2 批量拆分 将一个完
  • 2017“编程之美”终章:AI之战勇者为王

    编者按 8月15日 第六届微软 编程之美 挑战赛在选手的火热比拼中圆满落下帷幕 编程之美 挑战赛是由微软主办 面向高校学生开展的大型编程比赛 自2012年起 微软每年都在革新比赛命题 紧跟时代潮流 如今的 编程之美 挑战赛已成为优秀学子切磋
  • 火爆科研圈的三维重建技术:Neural radiance fields (NeRF)

    如果说最近两年最火的三维重建技术是什么 相信NeRF 1 是一个绝对绕不过去的名字 这项强到逆天的技术 一经提出 就被众多研究者所重视 对该技术进行深入研究并提出改进已经成为一个热点 仅仅过了不到两年的时间 NeRF及其变种已经成为重建领域
  • 【golang基础】校验和计算

    首先 IP ICMP UDP和TCP报文头都有检验和字段 大小都是16bit 算法基本上也是一样的 在发送数据时 为了计算数据包的检验和 应该按如下步骤 1 把校验和字段设置为0 2 把需要校验的数据看成以16位为单位的数子组成 依次进行二
  • UE4 读取Json

    UE4 读取Json 添加模块 Json JsonUtilities PublicDependencyModuleNames AddRange new string Core CoreUObject Engine InputCore Jso
  • YOLOv5另一种好用的数据集存放格式(附划分代码及查看每个类别分布情况)

    一 以前用的数据集格式 训练集 测试集的图片和标签分别放在对应的文件夹里 这就导致一个问题 如果相对数据集多次随机划分的话 就要多次从总的图片和标签中选择出需要的图片和标签 并且保存到相应的文件夹中 这样会很麻烦 而且浪费时间 二 改进 将
  • 此URL不支持Http方法GET解决方案

    一 问题 问题代码如下 WebServlet demo3 public class ServletDemo3 extends HttpServlet Override protected void doGet HttpServletRequ
  • insert()方法

    insert 方法 描述 列表 insert 方法将指定对象插入到列表中的指定位置 语法 insert 方法语法 L insert index obj 参数 index 对象obj需要插入的索引值 obj 要插入列表中的对象 返回值 该方法
  • 将Minio获取到的图片直接在页面上预览

    在Minio中获取的文件返回的是二进制流 要想在浏览器页面直接预览就得把获取的二进制流 InputStream 转换成文件流 FileInputStream 具体实现代码如下 public byte getImage PathVariabl
  • 大意了~checksum 到的低级问题

    发送的数据需要在尾端做累加取反 但没有留意到最后一个字节 累加取反值 不用参与累加 因此累加值总是不对 浪费了好多时间
  • php导出excel 下载,excel的导出和下载(实例讲解)

    1 前言 有时需要将数据库表资源导出excel 做成一些报表数据 而php导出excel的方法大致有几种 1 使用php的类库 进行导出 如PHPExcel 2 使用php原生的方法进行导出 而本文介绍的就是 如何通过原生方法导出excel
  • pandas筛选、修改并实现分类

    虽然学pandas有段时间了 但是真正应用的场合其实很少 大多数功能用excel就已经足够 最近发现wps表格某些功能比 excel还好用 比如筛选重复身份证 wps表格就做得比excel2016要好 最近发现了一个比较麻烦的问题 表格内容
  • JAVA中的术语:句柄是啥意思

    句柄的本质 一个唯一的整数 作为对象的身份id 区分不同的对象 和同类中的不同实例 程序可以通过句柄访问对象的部分信息 句柄不代表对象的内存地址 句柄和指针的区别 程序不能通过句柄直接阅读文件中的信息 指针是可以的 从所起的作用这点来说 句
  • 【项目实战】C语言+easyX带你实现:数字拼图游戏!来试试吧~

    每天一个编程小项目 提升你的编程能力 这是一个简易的拼图游戏 一共有 15 个数字方块 将其一行行的排列为 1 15 即可完成 游戏会记录下完成拼图的时间 我想说的是 很多时候 精彩的游戏不一定非要用图片 将游戏的功能和手感都做好 游戏一样
  • 卫星通信系统概述

    卫星通信系统指通过在轨人造卫星作为中继站对无线电信号进行转发 实现地面及空间等用户之间信息传输的系统 卫星通信系统组成包括空间段及地面段 系统组成如图所示 其中空间段主要指在轨卫星 对在轨卫星进行操控的地面站 这些地面站主要实现跟踪 遥测
  • 《QDebug 2023年8月》

    一 Qt Widgets 问题交流 1 获取 QWidget 当前所在屏幕区域 本来以为 QWidget 的 screen 接口返回的是组件自己所在屏幕的 QSreen 实测是所属 Window 所在的屏幕 如果 Window 跨屏了两者所
  • Android 内存分析工具

    Dalvik 虚拟机支持垃圾收集 但是这不意味着你可以不用关心内存管理 你应该格外注意移动设备的内存使用 手机和平板的内存空间是受到限制的 在这篇文章里面 我们来看看Android SDK里面的一些内存剖析工具 profiling tool