性能优化之使用Memory Analyzer

2,418 阅读4分钟

一、简介

在 Android 开发中,内存分析是一个非常重要的环节,它可以帮助你识别和解决内存泄漏、内存使用过多等问题。以下是一个简单的内存分析示例,展示了如何使用 Android Studio 的内存分析工具(如 Memory Profiler)来检测和解决内存泄漏问题。

假设我们有一个简单的 Android 应用,其中包含一个可能导致内存泄漏的代码片段。我们将通过内存分析工具来检测这个内存泄漏。

例子:静态持有activity引用的分析

image.png

或者通过adb命令:adb shell dumpsys meminfo 应用包名,快速进行内存分析查看,观测activities的数量

image.png

一、通过Android studio工具生成文件

抓取记录内存片段,那该如何抓取,可以通过Android studio自带的 profile 工具 详细步骤如下:

  1. 打开Android Studio:启动你的Android Studio并打开你的项目。

  2. 连接设备:确保你的Android设备通过USB连接到电脑,或者使用Android模拟器。

  3. 启动应用:在Android Studio中运行你的应用。

  4. 打开Profiler工具:在Android Studio中,点击右上角的Profiler标签,或者通过菜单View > Tool Windows > Profiler打开Profiler窗口。

  5. 选择设备和进程:在Profiler窗口中,选择你连接的设备和正在运行的应用进程。

  6. 选择Memory Profiler:在Profiler窗口中,点击Memory标签以打开内存分析工具。

  7. 启动内存分析:点击Record按钮(红色圆点)开始记录内存使用情况。

  8. 执行操作:在应用中执行你怀疑可能导致内存泄漏的操作。

  9. 停止记录:完成操作后,点击Stop按钮(红色方块)停止记录。此时,Profiler会生成一个内存快照。

  10. 查看内存快照:在Memory Profiler中,你可以看到内存使用情况的图表。点击图表中的任意位置,可以查看特定时间点的内存快照。

  11. 分析堆内存:点击Dump Java Heap按钮生成堆内存快照。生成的堆内存快照会显示应用在特定时间点的内存分配情况。

  12. 查找泄漏对象:在堆内存快照中,查找可能的内存泄漏对象。你可以通过以下方法查找泄漏对象:

    • Activity/Fragment泄漏:查找未被正确释放的Activity或Fragment实例。
    • 大对象泄漏:查找占用大量内存的大对象。
    • 引用链分析:点击泄漏对象,查看引用链,找到导致对象无法被垃圾回收的原因。

上面的详细流程在下面几张图中已经详细标注出来,可仔细查看 image.png

生成记录片段,进行下载,导出保存 image.png 上图4个泄漏,点击步骤后,找到了MemoryLeakActivity,记住该类后续用分析工具的时候,可以去检索他

image.png 按步骤,找到泄漏点,但这里可用信息少了点,经验丰富的人可以看出问题所在(sCallBacks),但是分析工具可以更详细,后续会说到

image.png

二、下载eclipse memory analyzer工具,注意版本,下载地址:www.eclipse.org/mat/previou…

我下载的这个版本11.0.20201202,当时下载的最新的,打开后提示报错:java版本不兼容,这个自行选择版本去下载

image.png

将Android studio 的profile文件生成的hprof文件,使用命令转化,才能被eclipse memory analyzer工具打开: 命令如下:

找到自己的sdk,platform-tools文件夹使用命令
 C:\Users\admin\AppData\Local\Android\Sdk\platform-tools> hprof-conv F:\泄漏profile文件分析\memory-20221220T175022.hprof F:\泄漏profile文件分析\hhh.hprof

后面打开你使用上面命令生成的F:\泄漏profile文件分析\hhh.hprof文件,如下图进行分析 image.png

步骤如下:打开histogram(直方图),可以查看某个class具体有多少实例。

image.png 搜索检测你想要的问题对象类,该问题类,可以从Android studio的profile 文件分析中看出是哪个

image.png

搜索MemoryLeakActivity下图显示有三个,这显然有问题,发生了泄漏 image.png

如下图右键选择,找到with incoming references--被哪些类所引用,而 with outgoing reference---代表我引用了哪些类,查看强引用相关的

image.png

强引用找到后查看如下图:

image.png

查看所有引用,因为这里是强引用,所以直接看就行

image.png

如下图找到了sCallBacks,被CallBackManager持有,而CallBackManager为静态

image.png

总结:使用profile初步观察,然后使用Memory Analyzer工具详细查看,然后结合代码确认泄漏点