当前位置: 首页 > news >正文

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线程所带来的内存泄露。

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

相关文章:

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

android 如何分析应用的内存(十七)——使用MAT查看Android堆 前一篇文章,介绍了使用Android profiler中的memory profiler来查看Android的堆情况。 如Android 堆中有哪些对象,这些对象的引用情况是什么样子的。 可是我们依然面临…...

Spring 使用注解储存对象

文章目录 前言存储 Bean 对象五大注解五大注解示例配置包扫描路径读取bean的示例 方法注解 Bean Bean 命名规则重命名 Bean 前言 通过在 spring-config 中添加bean的注册内容,我们已经可以实现基本的Spring读取和存储对象的操作了,但在操作中我们发现读…...

一、初始 Spring MVC

文章目录 一、回顾 MVC 模式二、初始 Spring MVC2.1 Spring MVC 核心组件2.1.1 前端控制器(DispatcherServlet)2.1.2 处理器映射器(HandlerMapping)2.1.3 处理器适配器(HandlerAdapter)2.1.3 后端控制器&am…...

《爬虫》爬取页面图片并保存

爬虫 前言代码效果 简单的爬取图片 前言 这几天打算整理与迁移一下博客。因为 CSDN 的 Markdown 编辑器很好用 ,所以全部文章与相关图片都保存在 CSDN。而且 CSDN 支持一键导出自己的文章为 markdown 文件。但导出的文件中图片的连接依旧是 url 连接。为了方便将图…...

【项目部署】JavaScript解析JSON解析报错Unexpected token xxx is not valid JSON

问题背景 这个报错发生在之前部署的一个前后端分离的项目中。后端使用的Spring Boot,前端使用的JavaScript,前后端交互使用Thymeleaf框架。 现象 项目组的另一个小伙伴说,突然有个页面打不开了,整个页面全空白。我F12打开浏览器…...

做接口测试如何上次文件

在日常工作中,经常有上传文件功能的测试场景,因此,本文介绍两种主流编写上传文件接口测试脚本的方法。 首先,要知道文件上传的一般原理:客户端根据文件路径读取文件内容,将文件内容转换成二进制文件流的格式…...

Java SPI机制详解-01

1. 概述 SPI(Service Provider Interface),是 Java 6 引入了一个内置功能,实现服务提供发现和加载机制,使之与特定接口的匹配。 SPI 机制的核心思想就是 解耦 ,将装配的控制权移到程序之外,这…...

由浅入深C系列六:C中实现字符串trim的功能

C中实现字符串trim的功能 简介设计思路代码实现运行效果 简介 一个项目中,需要用c语言实现对字符串中的字定字符进行过滤并从字符串的删除,查询了C语言的基本库,没有发现有这样的函数,于是发挥程序员的主观能力性,自力…...

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键(复制、另存为等)操作,对用户来说体验感会降低,但是又不希望自己的原创内容直接被copy,今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示: 复制以下代码,将其…...

ubuntu下nfs服务安装

操作系统:ubuntu22.04.2 一、服务端安装与配置 1、在服务端安装nfs服务端组件 sudo apt install nfs-kernel-server 2、创建共享目录share并且授权所有人可以访问 sudo mkdir /shared sudo chmod -R 777 /shared 3、配置nfs sudo vim /etc/exports 这将允许…...

Unity框架学习--2

接上文 IOC 容器是一个很方便的模块管理工具。 除了可以用来注册和获取模块,IOC 容器一般还会有一个隐藏的功能,即: 注册接口模块 抽象-实现 这种形式注册和获取对象的方式是符合依赖倒置原则的。 依赖倒置原则(Dependence I…...

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果iOS

WebRTC音视频通话-实现GPUImage视频美颜滤镜效果 在WebRTC音视频通话的GPUImage美颜效果图如下 可以看下 之前搭建ossrs服务,可以查看:https://blog.csdn.net/gloryFlow/article/details/132257196 之前实现iOS端调用ossrs音视频通话,可以查…...

82. 删除排序链表中的重复元素 II

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 解题思路:设置一个新的哑元节点result,作为头节点,将head中不重复地节点依次链接到哑元节点后面,最后返回result.next 初始值&…...

centos 7.x 单用户模式

最近碰到 centos 7.9 一些参数设置错误无法启动系统的情况,研究后可以使用单用户模式进入系统进行恢复操作。 进入启动界面,按 e ro 替换为 rw init/sysroot/bin/sh 替换前 替换后 Ctrl-x 进行重启进入单用户模式 执行 chroot /sysroot 可以查看日…...

取证--理论

资料: 各比赛 Writeup : https://meiyacup.cn/Mo_index_gci_36.html 哔站比赛复盘视频: https://space.bilibili.com/453117423?spm_id_from333.337.search-card.all.click 自动分析取证四部曲 新建案例添加设备自动取证制作报告 取证大…...

Tik Tok娱乐+电商MCN怎么做?

在美国外的热门市场中,TikTok 主要做的区域市场包括中东、拉美、欧洲和东亚,而这里面适合做电商的其实并不多。 欧洲、东亚都属于成熟市场,且 TikTok 本身在欧洲面临 DSA 法案更严格的审查,与在英国相同,欧洲各市场消…...

java 自定义xss校验注解实现

自定义一个注解Xss。名字随意 import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Targe…...

Selenium图片滑块验证码

因为种种原因没能实现愿景的目标,在这里记录一下中间结果,也算是一个收场吧。这篇文章主要是用selenium解决滑块验证码的个别案列。 思路: 用selenium打开浏览器指定网站 将残缺块图片和背景图片下载到本地 对比两张图片的相似地方&#…...

CAP理论与MongoDB一致性,可用性的一些思考

正文 大约在五六年前,第一次接触到了当时已经是hot topic的NoSql。不过那个时候学的用的都是mysql,Nosql对于我而言还是新事物,并没有真正使用,只是不明觉厉。但是印象深刻的是这么一张图片(后来google到图片来自这里&…...

lc2536.子矩阵元素加1

暴力解法:直接按照题目所示在矩阵的相应位置加一 时间复杂度:O(n2 * queries.length) 空间复杂度:O(1) 二维差分:创建二维差分数组,通过对差分数组的修改来影响原来的数组,最后还原 时间复杂度&#x…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性&#xf…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

GitHub 趋势日报 (2025年06月06日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...