性能优化Android开发经验谈Android开发

Android内存优化工具:Memory Profiler

2019-08-03  本文已影响17人  小村医

一、简介

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

二、为什么应分析您的应用内存

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

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

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

三、Memory Profiler 概览

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


打开 Memory Profiler.png

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


Memory Profiler.png

如图 1 所示,Memory Profiler 的默认视图包括以下各项:

  1. 用于强制执行垃圾回收 Event 的按钮。
  2. 用于捕获堆转储的按钮。
  3. 用于记录内存分配情况的按钮。 此按钮仅在连接至运行 Android 7.1 或更低版本的设备时才会显示。
  4. 用于放大/缩小时间线的按钮。
  5. 用于跳转至实时内存数据的按钮。
  6. Event 时间线,其显示 Activity 状态、用户输入 Event 和屏幕旋转 Event。
  7. 内存使用量时间线,其包含以下内容:
    • 一个显示每个内存类别使用多少内存的堆叠图表,如左侧的 y 轴以及顶部的彩色键所示。
    • 虚线表示分配的对象数,如右侧的 y 轴所示。
    • 用于表示每个垃圾回收 Event 的图标。

如何计算内存

您在 Memory Profiler 顶部看到的数字取决于您的应用根据 Android 系统机制所创建的所有私有内存。 此计数不包含与系统或其他应用共享的内存。


内存计数.png

内存计数中的类别如下所示:

四、查看内存分配

内存分配显示内存中每个对象是如何分配的。 具体而言,Memory Profiler 可为您显示有关对象分配的以下信息:

如果您的设备运行 Android 8.0 或更高版本,您可以随时按照下述方法查看您的对象分配: 只需点击并按住时间线,并拖动选择您想要查看分配的区域(如下图所示)。 不需要开始记录会话,因为 Android 8.0 及更高版本附带设备内置分析工具,可持续跟踪您的应用分配。


image.gif

要检查分配记录,请按以下步骤操作:

五、捕获堆转储

堆转储显示在您捕获堆转储时您的应用中哪些对象正在使用内存。 特别是在长时间的用户会话后,堆转储会显示您认为不应再位于内存中却仍在内存中的对象,从而帮助识别内存泄漏。 在捕获堆转储后,您可以查看以下信息:

要捕获堆转储,在 Memory Profiler 工具栏中点击 Dump Java heap 。 在转储堆期间,Java 内存量可能会暂时增加。 这很正常,因为堆转储与您的应用发生在同一进程中,并需要一些内存来收集数据。

堆转储显示在内存时间线下,显示堆中的所有类类型,如上图所示。

如果您需要更精确地了解转储的创建时间,可以通过调用 dumpHprofData() 在应用代码的关键点创建堆转储。

要检查您的堆,请按以下步骤操作:

  1. 浏览列表以查找堆计数异常大且可能存在泄漏的对象。 为帮助查找已知类,点击 Class Name 列标题以按字母顺序排序。 然后点击一个类名称。 此时在右侧将出现 Instance View 窗格,显示该类的每个实例,如图 5 中所示。
  2. Instance View 窗格中,点击一个实例。此时下方将出现 References,显示该对象的每个引用。
    或者,点击实例名称旁的箭头以查看其所有字段,然后点击一个字段名称查看其所有引用。 如果您要查看某个字段的实例详情,右键点击该字段并选择 Go to Instance
  3. References 标签中,如果您发现某个引用可能在泄漏内存,则右键点击它并选择 Go to Instance。 这将从堆转储中选择对应的实例,显示您自己的实例数据。

默认情况下,堆转储不会向您显示每个已分配对象的堆叠追踪。 要获取堆叠追踪,在点击 Dump Java heap 之前,您必须先开始记录内存分配。 然后,您可以在 Instance View 中选择一个实例,并查看 Call Stack 标签以及 References 标签,如图 5 所示。不过,在您开始记录分配之前,可能已分配一些对象,因此,调用堆栈不能用于这些对象。 包含调用堆栈的实例在图标

堆栈实例在图标

上用一个“堆栈”标志表示。 (遗憾的是,由于堆叠追踪需要您执行分配记录,因此,您目前无法在 Android 8.0 上查看堆转储的堆叠追踪。)

在您的堆转储中,请注意由下列任意情况引起的内存泄漏:

捕获堆转储需要的持续时间标示在时间线中.png

在类列表中,您可以查看以下信息:

在类列表顶部,您可以使用左侧下拉列表在以下堆转储之间进行切换:

默认情况下,此堆中的对象列表按类名称排列。 您可以使用其他下拉列表在以下排列方式之间进行切换:

默认情况下,此列表按 Retained Size 列排序。 您可以点击任意列标题以更改列表的排序方式。
在 Instance View 中,每个实例都包含以下信息:

将堆转储另存为 HPROF

要使用其他 HPROF 分析器(如MAT),您需要将 HPROF 文件从 Android 格式转换为 Java SE HPROF 格式。 您可以使用 android_sdk/platform-tools/ 目录中提供的 hprof-conv 工具执行此操作。 运行包括以下两个参数的 hprof-conv 命令:原始 HPROF 文件和转换后 HPROF 文件的写入位置。 例如:

hprof-conv heap-original.hprof heap-converted.hprof

上一篇下一篇

猜你喜欢

热点阅读