Android 性能优化(五)Heap Dump 的使用

Android Profiler

在新版的 Android studio 中, Profiler 的界面发生了变化,如下图所示。

其中:

  • System Trace:显示整个系统的活动和资源使用情况。比如:应用和系统进程在设备核心和线程中的分布情况;界面渲染的流畅程度;设备和应用级别的耗电量
  • Heap Dump:用于收集和分析堆转储,一般使用这个来分析内存
  • Callstacks Sample:对调用堆栈进行抽样,可以在这里找到调用时间比较长的代码段
  • Java/Kotlin Allocations:记录 Java/Kotlin 分配。比如:分配了哪些类型的对象以及它们使用多少空间;每个分配的堆栈轨迹,包括在哪个线程中。
  • Java/Kotlin Method Recording:记录应用代码执行期间调用的 Java/Kotlin 方法,可让我们查看特定时间点的调用堆栈和 CPU 使用情况(已过滤为仅显示 Java/Kotlin 方法)。此数据有助于识别执行时间长或消耗大量系统资源的代码段。
  • Native Allocations:原生代码表示的对象的分配和解除分配情况
  • View Live Telemetry: 用于实时检查应用,可以大致了解设备的 CPU 使用情况、线程活动和内存使用情况。

这篇文章将介绍新版 Profiler 中,Heap Dump 的使用

Heap Dump

启动 Heap Dump 分析后,可以捕获当前的内存中所有对象的快照,如下图所示:

注意:在转储堆期间,Java 内存量可能会临时性增加。这是因为堆转储需要一些内存来收集数据。

下拉菜单

Heap Dump 界面的第一行有三个下拉菜单,其作用分别是:过滤特定的堆内存分配排列方式指定 Class

过滤特定的堆

如下图所示:

  • View all heaps:查看所有堆
  • View app heap(默认):查看 App 在其中分配内存的主堆
  • View image heap:系统启动映像,包含启动期间预加载的类,此处的分配确保绝不会移动或消失
  • View zygote heap:写时复制堆,其中的应用进程是从 Android 系统中派生的

内存分配排列方式

如下图所示:

  • Arrange by class(默认):默认根据类名对所有分配进行分组
  • Arrange by package:根据软件包名对所有分配进行分组

过滤 Class

如下图所示:

  • Show all classes(默认):显示所有类,包括库中的类 和依赖项
  • Show activity/fragment Leaks:展示泄露的 Activity/Fragment
  • Show project class:仅显示项目定义的类

类列表

设置好第一行的下拉菜单后,我们就可以在类列表中查看对应的内存使用情况。这里以 过滤 Class 设置为 Show project class 为例,如下图所示:

可以看到其中:

  • Classes:指类的种类
  • Leaks:展示泄露数量,双击会自动选中 Show activity/fragment Leaks
  • Count:堆中对象的分配数量
  • Native Size:此对象类型使用的原生内存总量(单位字节)
  • Shallow Size:指的是对象实例自身占用的内存大小,不包括它引用的其他对象的内存。(单位字节)
  • Retained Size :是该对象及其独占引用的其他对象(基于支配树 dominator tree)的总内存大小(单位字节)

注意:Native Size 只有在使用 Android 7.0 及更高版本时,才会看到此列,会在此处看到采用 Java 分配的某些对象的内存,因为 Android 对某些框架类(如 Bitmap)使用原生内存

假设对象的依赖关系如下图所示,此时

css 复制代码
Shallow Size = size(A)

// 由于对象 B 只被对象A引用,如果对象A被回收,那么对象B也会被回收
Retained Size = size(A) + size(B)

如果 B 对象被其他对象引用,则此时

txt 复制代码
Shallow Size = size(A)

// 由于对象 B 同时被对象A和对象C引用,如果对象A被回收,那么对象C不会被回收
Retained Size = size(A)

更多关于 Shallow Size & Retained Size 具体可以看 Android优化篇|Shallow Size & Retained Size

上图所示,是具体的类所占用的内存。其中 Allocations 是指堆中的对象的分配数,和 Count 是相同的。

注意,Retained Size 一定是大于或者等于 Shallow Size 的。在 heap dump 的界面中,有时候会出现 Retained Size 小于 Shallow Size 的情况,这可能是 Android studio 的bug,具体可以看 issuetracker.google.com/issues/2820...

内存泄漏

点击 Leaks 或者选择 Show activity/fragment Leaks 可以展示内存泄漏界面,如下图所示:

如下图所示,对于 LeakActivity 对象,其中 Depth 是指从任意 GC 根到选定实例的最短跳数。

点击泄漏的 LeakActivity 对象,可以看到该对象的实例详情,如下所示。

其中:

  • Fields:显示此实例中的所有字段。
  • References:显示对 Instance 标签页中突出显示的对象的每个引用。

对于内存泄漏的排查,一般我们需要选中 Show nearest GC root only,显示最近的 GC root。通过这个来排查哪里还在引用该 Activity 或者 Fragment。

注意:在以下情况中可能会产生误报的问题:

  • 已创建 Fragment,但尚未使用它。
  • 正在缓存 Fragment,但它不是 FragmentTransaction 的一部分

由于在此界面,无法直接强制触发 GC,我们需要通过以下方式来实现类似的效果:

  • 将设备从竖屏旋转为横屏,然后反复旋转多次 在不同 activity 状态下使用。
  • 当处于不同的 activity 状态时,在我们的应用与其他应用之间切换。 例如,导航到主屏幕,然后返回我们的应用。

参考

相关推荐
阿华的代码王国2 小时前
【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
android·xml·java·前端·后端
EngZegNgi2 小时前
Unity —— Android 应用构建与发布
android·unity·自动化·游戏引擎·构建
fatiaozhang95272 小时前
烽火HG680-KX-海思MV320芯片-2+8G-安卓9.0-强刷卡刷固件包
android·电视盒子·刷机固件·机顶盒刷机
橙序员小站2 小时前
仍然嫌GC卡顿?新一代低延迟GC了解一下
java·jvm·性能优化
LiuYaoheng3 小时前
【Android】使用 Intent 传递对象的两种序列化方式
android·java·笔记·学习
啊森要自信3 小时前
【MySQL 数据库】MySQL索引特性(二)页目录&&(B和B+树)&&(非)聚簇索引 && 索引操作
android·数据库·sql·mysql·adb·数据库架构
穷人小水滴3 小时前
Android 运行 deno 的新方法 (3): Termux 胖喵安初
android·linux
穷人小水滴4 小时前
7 天充电宝计划 (小实验)
android·linux
jzlhll12311 小时前
android MVC/MVP/MVVM/MVI架构发展历程和编写范式
android·架构