android 如何分析应用的内存(十七)——使用MAT查看Android堆

android 如何分析应用的内存(十七)——使用MAT查看Android堆

前一篇文章,介绍了使用Android profiler中的memory profiler来查看Android的堆情况。
如Android 堆中有哪些对象,这些对象的引用情况是什么样子的。

可是我们依然面临一个比较严峻的挑战:不管是app开发者,还是内存分析者而言,堆中的对象,非常之多,不仅有Android 原生的类,还有第三方库使用的类。这些类在使用过程中,也可能因为有较大的shallow size 或者retained size而混淆内存的分析。

为了解决这样的问题,我们更希望,通过不同时间点的堆,进行差分比较。即在时刻t1生成的堆heap1和t2时刻生成的堆heap2进行相互比较。

为此,我们将介绍java开发中重要的内存分析工具MAT。

MAT使用前的准备

在上一篇文章中,我们使用AS捕获了堆,现在我们需要将其导出,用在MAT工具上。如下图:
在这里插入图片描述

接下来将Android保存的heap dump进行格式转换,以满足MAT的需求。转换格式的工具在Android SDK中。如下:

/Users/biaowan/Library/Android/sdk/platform-tools/hprof-conv ./mat/memory-test_malloc_int\[\].hprof mat_test1.hprof

在这里插入图片描述

MAT的使用

打开MAT之后,进入菜单栏->File->Open File。然后选择刚才转换之后的mat_test.hprof文件。如下图
在这里插入图片描述

可见,主界面显示一个overview的界面,该界面用英文详细表述了具体细节,不在赘述。下面解释上图的八个标记。

  • 标记1:打开overview 界面。即上面的主界面。

  • 标记2:打开当前堆中的对象分布情况,默认按照类名进行排序。右键可以进行相应操作,各个操作什么意思,已经标明。如下图
    在这里插入图片描述

  • 标记3:显示本heap中的所有dominator tree(注意:dominator tree,已经在上一篇文章中介绍:android 如何分析应用的内存(十六)——使用AS查看Android堆:http://t.csdn.cn/GTWpR). 而各个对象应该怎么查看其对应的dominator tree。见标记2对应的右键说明。

  • 标记4:Open Object Qurey Language,类似于使用SQL语句进行查询。因为MAT提供的菜单功能已经完全够Android使用,因此本文不再介绍

  • 标记5:展示线程的名字,堆栈,本地变量等。但是Android 没有提供这个功能,因此无法使用

  • 标记6:打印各种报告,如下图标记
    在这里插入图片描述

  • 标记7:即为标记2中,右键支持的各种操作,详见标记2

  • 标记8:搜索按钮,可以按照地址进行搜索

为了能够详细说明,如何操作MAT,下文将会以各种问题作为模板,详细介绍操作过程

问题1:如何查看某个类有哪些对象

  1. 点击标记1,打开所有类的列表。
  2. 在第一行,键入需要查找的类,或者按照不同的大小进行排序和过滤
  3. 选中类,然后点击右键,选择List Objects.然后按照需求列出各个对象
    在这里插入图片描述

问题2:如何查看某个对象到GC root的引用链

  1. 选中某个对象,右键选中Paths to GC root
  2. 再次选中exclude all xxx references
    在这里插入图片描述

可见整个引用链清晰明了,不在绘图说明

问题3:如何查看对象的Dominator tree(支配树)

  1. 选中对象,右键选择Java Basics
  2. 再次选中Open in Dominator tree
  3. 在弹出的框中,选择finish。默认以对象排序
    在这里插入图片描述

从图中可以看到TaskRunable对象直接支配两个对象,一个int数组,一个弱引用

问题4:如何查看一个对象的直接支配者

  1. 选中对象,然后右键,选择immediate dominator
  2. 在弹出框中,选择finish
    在这里插入图片描述

可以看到我们选中的TaskRunable对象的直接支配者是一个Task对象

问题5:如何查看类加载器,是否重复加载同一个类

  1. 点击标记1,打开overview界面
  2. 滚动界面到最底下
  3. 选择Duplicate classes
    在这里插入图片描述

问题6:如何查看堆中,最占内存的部分

  1. 点击标记1,打开overview界面
  2. 滚动至最底下
  3. 选择Top cosumer
    在这里插入图片描述

从图中可以看到,分别按照对象,类,类加载器,包名列出了最占内存的部分

问题7:如何查看堆的报告

  1. 点击标记6.选择Heap dump overview
  2. 在对报告中,点击table of content 查看内容表(该字段,在报告的底部)
    在这里插入图片描述

从中也可以直接查看最占内存的对象

问题8:如何进行泄露检查

  1. 点击标记6,选择Leak Suspect
    在这里插入图片描述

从图中可以看到,有三个怀疑的对象,往下滚动,可以看到三个怀疑对象的详细细节,如下
在这里插入图片描述

图中,简要说明了Task类,有2100个实例,占了29.51%的内容。点击details它会显示相应的引用链路径。可清晰看到GC root的整个引用链。

多个Heap进行差分分析,查找内存问题

为了一步步演练,如何使用多个heap进行差分分析,我们选择上一篇文章方案2中的例子:android 如何分析应用的内存(十六)——使用AS查看Android堆:http://t.csdn.cn/JYGFC。然后在同一个进程的两个不同时刻,分别选取不同的heap,分别叫as_heap1.hprof和as_heap2.hprof.

场景1:MAT 自动分析两个堆之间的内存泄露

  1. 按照上文提及的hprof-conv工具,将as_heap1.hprof,as_heap2.hprof分别转换为mat_heap1.hprof,mat_heap2.hprof。然后用mat工具将其打开。

  2. 打开第二个heap的overvie操作栏,即标记1。滚动到最底部

  3. 选择Leak suspects by Snapshot comparision.

  4. 在弹出的框中,选择mat_heap1.hprof。然后点击finish。让mat_heap2.hprof与mat_heap1.hprof做差分分析,然后给出一个报告,如下(需要等待一段时间)
    在这里插入图片描述
    在这里插入图片描述

从图中可以看到,怀疑com.example.test_malloc.Task对象泄露,它有4900个对象,占整个堆的49.26%。点击details可以看到这个引用链,如下图
在这里插入图片描述

从图中可以看到,Task被DeviceManager的listener所持有,导致GC无法回收。所以找到了内存泄露点。

场景2:无法自动分析时,手动分析

当两个heap堆,间隔时间较短,泄露的对象,占据整个堆的空间较小,此时mat无法进行自动分析。此时我们可以手动分析。

接下来,我们用时间间隔较小的两个堆,分别叫mat_heap3.hprof和mat_heap4.hprof

注意:mat_heap3.hprof和mat_heap4.hprof是用AS 重新抓取的时间间隔较近的两个堆

  1. 用mat打开mat_heap3.hprof,和mat_heap4.hprof

  2. 按照问题6,输出消耗内存最大的部分。下面是mat_heap3.hprof的报告。
    在这里插入图片描述

从中,我们看到,占据内存最大的首要对象是int数组。接下来我们手动分析两个堆中的int数组之间的差距——即mat_heap4.hprof比mat_heap3.hprof多了哪几个int数组

  1. 点击mat_heap3.hprof的统计信息,即标记2.然后选中int[]。右键列出所有的对象。如下图
    在这里插入图片描述

  2. 点击操作历史记录栏,右键list_objects… 然后点击add to compare basket。如下图
    在这里插入图片描述

  3. 因为我们需要比较两个heap堆的int[]情况,因此选中mat_heap4.hprof之后,按照步骤3,4做同样操作。将会在compare basket窗口两个需要比较的对象。然后点击感叹号,开始比较即可。如下:
    在这里插入图片描述

对测试结果,进行简单排序,shallow_heap #1 升序排列。即可展示heap3中没有而heap4中具有的对象。这也是从抓取heap3时刻,到抓取heap4时刻之间,堆中多出来的int数组对象。为前排的10个对象。

按照前文的问题2即可查看其引用链,从而分析被谁持有,为何没有被释放掉。

在第2步中,输出的top comsumer除了int数组以外,还有其他的对象,因此按照步骤3,4,5即可进行两个堆的比较。我们已经以int[]为例子,做了详细说明,就不再一一比较。

除了使用top comsumer辅助定位需要比较的对象以外,还可以对任何怀疑的对象进行比较。步骤完全相同。

至此,MAT的使用介绍完毕。

MAT弥补了AS在内存分析上的如下不足:

  • 无法自定义Retained Set(这对于大型应用很有用)
  • 无法进行地址查找
  • 无法进行堆之间的比较
  • 无法按照需要进行排序
  • 无法按照需要进行过滤等

虽然MAT已经足够强大,但是依然还有一个内存问题,悬而未决——怎么才能知道这些内存泄露是由哪一个线程触发,它们又有怎样的调用栈?

在多线程编程中,对象的泄露,即可能是对象之间的引用不合理,也可能是线程之间的逻辑不合理,如生产线程和消费线程不够合理等等。MAT无法解决Android线程所带来的内存泄露。

接下里,请期待如何用工具找到这种多线程带来的内存泄露。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/86350.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flink kafka消费者如何处理kafka主题的rebalance

背景: 我们日常使用kafka客户端消费kafka主题的消息时,当消费者退出/加入消费者组,kafka主题分区数有变等事件发生时,都会导致rebalance的发生,此时一般情况下,如果我们不自己处理offset,我们不…

深入理解PyTorch中的NoamOpt优化器

深入理解PyTorch中的NoamOpt优化器 作者:安静到无声 个人主页 今天,我们将深入探讨一个在自然语言处理领域广泛使用的优化器——NoamOpt。这个优化器是基于PyTorch实现的,并且在"Attention is All You Need"这篇论文中首次提出。…

c++11-14-17_内存管理(RAII)_多线程

文章目录 前言:什么是RAII?指针/智能指针:使用智能指针管理内存资源:unique_ptr的使用:自定义删除器: shared_ptr的使用:shared_ptr指向同一个对象的不同成员:自定义删除函数&#x…

centos7 安装桌面

先装 xrdp $ sudo yum install -y epel-release $ sudo yum install -y xrdp $ sudo systemctl enable xrdp $ sudo systemctl start xrdp开防火墙端口 $ sudo firewall-cmd --add-port3389/tcp --permanent $ sudo firewall-cmd --reload比较喜欢 GNOME $ sudo yum groupin…

Stable Diffusion - 幻想 (Fantasy) 风格与糖果世界 (Candy Land) 人物提示词配置

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/132212193 图像由 DreamShaper8 模型生成,融合糖果世界。 幻想 (Fantasy) 风格图像是一种以想象力为主导的艺术形式,创造了…

Vue.js2+Cesium1.103.0 七、Primitive 绘制航线元素

Vue.js2Cesium1.103.0 七、Primitive 绘制航线元素 用 Primitive 绘制航线元素,包括航点图标,航线线段,线段距离标注,航点序号,海拔标注,总航程等信息。 可同时绘制多条航线;可根据 id 清除指…

亚马逊 EC2服务器下部署java环境

1. jdk 1.8 安装 1.1 下载jdk包 官网 Java Downloads | Oracle tar.gz 包 下载下来 1.2 本地连接 服务器 我用的是亚马逊的ec2 系统是 ubuntu 的 ssh工具是 Mobaxterm , 公有dns 创建实例时的秘钥 链接 Mobaxterm 因为使用的 ubuntu 所以登录的 名称 就是 ubuntu 然后 …

php代码审计,php漏洞详解

文章目录 1、输入验证和输出显示2、命令注入(Command Injection)3、eval 注入(Eval Injection)4、跨网站脚本攻击(Cross Site Scripting, XSS)5、SQL 注入攻击(SQL injection)6、跨网站请求伪造攻击(Cross Site Request Forgeries, CSRF)7、Session 会话劫持(Session Hijacking…

基于DETR (DEtection TRansformer)开发构建MSTAR雷达影像目标检测系统

关于DETR相关的实践在之前的文章中很详细地介绍过,感兴趣的话可以自行移步阅读即可: 《DETR (DEtection TRansformer)基于自建数据集开发构建目标检测模型超详细教程》 《书接上文——DETR评估可视化》 基于MSTAR雷达影像数据开发构建目标检测系统&am…

双向循环链表、dancing links

目录 双向循环链表 力扣 426. 将二叉搜索树转化为排序的双向链表 十字交叉双向循环链表(dancing links) 精确覆盖问题 dancing links X算法(V1递归版) POJ 3740 Easy Finding 数独 X算法优化 X算法(V2非递归…

手机app测试

一、安装、卸载、更新、运行 1.安装、卸载 应用是否可以正常安装(命令行安装;apk/ipa安装包安装)(有网,无网是否都正常)卸载过程中出现死机,断电,重启等意外的情况&…

关于ArrayList的十三连问

文章目录 一、底层存储结构是什么二、初始容量三、构造方法四、扩容原理五、读写速度比较六、克隆为深克隆还是浅克隆七、多线程环境下是否安全八、增强遍历时添加或删除元素会发生什么事情九、为什么数组被transient修饰十、通过subList()获得的集合能否转为ArrayList十一、使…

如何在 .NET Core WebApi 中处理 MultipartFormDataContent 中的文件

问题描述# 上图示例展示了用户通过 IOS 客户端发送请求时,对应后端接口接收到的 Request 内容。从请求内容的整体结果,我们可以看出这是一个 multipart/form-data 的数据格式,由于这种数据是由多个 multipart section 组成,所以我…

在next中使用antd表格,表格使用render函数报错

Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". {title: "姓名", dataIndex: "name", key: ..., render: function} 错误描述:使用antd的tabl…

【FAQ】安防监控视频EasyCVR平台分发的FLV视频流在VLC中无法播放

众所周知,TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入,包括主流标准协议国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。在视频流的处理与分发上,视频监控…

资深媒体人宋繁银加入《数据猿》任总编辑,全面负责公司整体内容工作

大数据产业创新服务媒体 ——聚焦数据 改变商业 2023年7月北京,《数据猿》宣布正式任命宋繁银为总编辑,全面负责公司整体内容工作。此次重要的人事任命标志着《数据猿》的发展迈上了一个新的台阶,对于《数据猿》团队而言,不仅是一…

LISA:通过大语言模型进行推理分割

论文:https://arxiv.org/pdf/2308.00692 代码:GitHub - dvlab-research/LISA 摘要 尽管感知系统近年来取得了显著的进步,但在执行视觉识别任务之前,它们仍然依赖于明确的人类指令来识别目标物体或类别。这样的系统缺乏主动推理…

谱包络之pysptk和pyworld

谱包络之pysptk和pyworld 谱包络可以直接用于语音的合成,常用的两个计算谱包络的库pysptk和pyword。 先看看代码: 一段语音x,采样率16000Hz pysptk import pysptkframe_length 1024 hop_length 80 order 25 alpha 0.41 frames libro…

个保新标 | 《信息安全技术 敏感个人信息处理安全要求》(征求意见稿)发布

8 月 9 日,全国信息安全标准化技术委员会公开发布关于国家标准《信息安全技术 敏感个人信息处理安全要求》(征求意见稿)(以下简称《标准》)的通知,面向社会广泛征求意见。 《标准》的制定背景是为支撑《个人…

k8s pod启动报错: no route to host

k8s pod kuboard启动报错 查看pod命令 kubectl get pods -A kubectl get pods --all-namespaces查看报错pod日志 命令: kubectl logs -f -n namespace nametime"2023-08-09T13:40:3608:00" levelerror msg"不能获取 AgentEndpointsGet \"http:/…