概述

Android Profiler分为三大模块: cpu、内存 、网络。下面,我们一次来讲解一下这个工具的使用。

内存分析器Memory Profiler

Memory Profiler 是 Android Profiler 中的一个组件,可帮助您识别导致应用卡顿、冻结甚至崩溃的内存泄漏和流失。 它显示一个应用内存使用量的实时图表,让您可以捕获堆转储、强制执行垃圾回收以及跟踪内存分配。

要打开 Memory Profiler,请按以下步骤操作:

  • 1、点击 View > Tool Windows > Android Profiler(也可以点击工具栏中的 Android Profiler )。
  • 2、从 Android Profiler 工具栏中选择您想要分析的设备和应用进程。 如果您通过 USB 连接了某个设备但该设备未在设备列表中列出,请确保您已启用 USB 调试。
  • 3、点击 **MEMORY **时间线中的任意位置可打开 Memory Profiler。或者,您可以在命令行中使用 dumpsys 检查您的应用内存,同时查看 logcat 中的 GC Event。

为什么使用内存分析器

Android 提供一个托管内存环境—当它确定您的应用不再使用某些对象时,垃圾回收器会将未使用的内存释放回堆中。 虽然 Android 查找未使用内存的方式在不断改进,但对于所有 Android 版本,系统都必须在某个时间点短暂地暂停您的代码。 大多数情况下,这些暂停难以察觉。 不过,如果您的应用分配内存的速度比系统回收内存的速度快,则当收集器释放足够的内存以满足您的分配需要时,您的应用可能会延迟。 此延迟可能会导致您的应用跳帧,并使系统明显变慢。

尽管您的应用不会表现出变慢,但如果存在内存泄漏,则即使应用在后台运行也会保留该内存。 此行为会强制执行不必要的垃圾回收 Event,因而拖慢系统的内存性能。 最后,系统被迫终止您的应用进程以回收内存。 然后,当用户返回您的应用时,它必须完全重启。

为帮助防止这些问题,您应使用 Memory Profiler 执行以下操作:

  • 1、在时间线中查找可能会导致性能问题的不理想的内存分配模式。
  • 2、转储 Java 堆以查看在任何给定时间哪些对象耗尽了使用内存。 长时间进行多个堆转储可帮助识别内存泄漏。
  • 3、记录正常用户交互和极端用户交互期间的内存分配以准确识别您的代码在何处短时间分配了过多对象,或分配了泄漏的对象

如需了解可减少应用内存使用的编程做法,请阅读管理您的应用内存。

内存分析器概述

当您首次打开 Memory Profiler 时,您将看到一条表示应用内存使用量的详细时间线,并可访问用于强制执行垃圾回收、捕捉堆转储和记录内存分配的各种工具。

如上图所示,内存分析器的默认视图包括以下内容:

  • ① 强制执行垃圾收集事件的按钮(触发垃圾回收)。出发垃圾回收,可以帮我们查看内存泄漏的情况。(记住:每次获取堆转储文件的时候,我们最好先手动执行垃圾收集)
  • ② 捕获堆转储的按钮(查看当前Java堆的情况,获取内存dump文件,生成一个.hprof文件)。
  • ③ 记录内存分配的按钮(查看一段时间内Java堆的变化)。
  • ④ 放大时间线的按钮。
  • ⑤ 跳转到实时内存数据的按钮。
  • ⑥ 事件时间线显示活动状态、用户输入事件和屏幕旋转事件。
  • ⑦ 内存使用时间表,其中包括以下内容:
    1、每个内存类别使用多少内存的堆栈图,如左边的y轴和顶部的颜色键所示。
    2、虚线表示已分配对象的数量,如右侧y轴所示。(比如,右侧的共计分配150000个对象)
    3、每个垃圾收集事件的图标。

但是,默认情况下并不是所有的分析数据都可见。如果您看到一条消息,说“Advanced profiling is unavailable for the selected process”,则需要启用高级分析以查看以下内容:Event时间表、分配对象的数量、垃圾收集事件。在 Android 8.0 及更高版本上,始终为可调试应用启用高级分析。

​ 提示: 与之前的Android监控工具相比,新的内存分析器记录了你的内存使用情况,所以看起来你的内存使用量会更高。内存分析器监视一些额外的类别,这些类别增加了总数,但如果您只关心Java堆内存,那么“Java”的数字应该与上一个Android监视器的值类似。新的号码记录了从Zygote分派到应用程序的Java堆中的所有物理内存页面,这准确表示您的应用程序实际使用多少物理内存。

内存计算方式

您在内存性能分析器顶部看到的数字(图 2)基于您的应用提交的所有专用内存页面(此数据由 Android 系统根据其记录提供)。此计数不包含与系统或其他应用共享的页面。

img

内存计数中的类别如下:

  • Java:从 Java 或 Kotlin 代码分配的对象的内存。

  • Native:从 C 或 C++ 代码分配的对象的内存。

    即使您的应用中不使用 C++,您也可能会看到此处使用了一些原生内存,因为即使您编写的代码采用 Java 或 Kotlin 语言,Android 框架仍使用原生内存代表您处理各种任务,如处理图像资源和其他图形。

  • Graphics:图形缓冲区队列为向屏幕显示像素(包括 GL 表面、GL 纹理等等)所使用的内存。(请注意,这是与 CPU 共享的内存,不是 GPU 专用内存。)

  • Stack:您的应用中的原生堆栈和 Java 堆栈使用的内存。这通常与您的应用运行多少线程有关。

  • Code:您的应用用于处理代码和资源(如 dex 字节码、经过优化或编译的 dex 代码、.so 库和字体)的内存。

  • Others:您的应用使用的系统不确定如何分类的内存。

  • Allocated:您的应用分配的 Java/Kotlin 对象数。此数字没有计入 C 或 C++ 中分配的对象。

查看内存分配

内存分配情况图表为您显示内存中每个 Java 对象和 JNI 引用的分配方式。具体而言,内存性能分析器可为您显示有关对象分配情况的以下信息:

  • 分配了哪些类型的对象以及它们使用多少空间。

  • 每个分配的堆栈轨迹,包括在哪个线程中。

  • 对象在何时被取消分配(仅当使用搭载 Android 8.0 或更高版本的设备时)。

如果您的设备搭载的是 Android 8.0 或更高版本,您可以随时查看对象分配,具体操作步骤如下:在时间轴上拖动以选择要查看哪个区域的分配(如视频 1 中所示)。不需要开始记录会话,因为 Android 8.0 及更高版本附带设备内置分析工具,可持续跟踪您的应用分配。

使用方法

1、首先,我们先找出我们怀疑存在内存泄漏的页面。

2、在进入这个内存泄漏的页面之前,我们先执行一次GC操作。

3、而后频繁进出测试页面。

4、如果发现内存再不断的进行增长。执行一段时间之后,我们再去执行一次GC操作。

5、然后DumpHeap内存。然后生成堆转储文件。

生成堆转储文件之后,我们就可以看到Android Profiler已经帮我们来捕捉到Android Activity的内存泄漏。

现在最新的Android Profiler 已经可以帮你初步分析内存泄漏。 我们点击上面警告:

image-20210713073249770

然后我们可以点击由此的Reference模块。勾选show nearest GC root only

image-20210713073437509

根据GC root的深度。我们就可以找到GC Root的对象。查找到内存泄漏的根源所在。