Android Profiler 内存分析

Android studio(下面简称AS)为App提供的性能分析工具,在AS3.0+替换掉旧的分析工具,对于其使用方法,官方也有对应的介绍:Android Profiler

对于使用方法,我只用到比较简单的功能,高级的还没用到,使用案例进行简答的使用,在此之前,你可能需要到官方文档中了解Profiler中一些字段的基本意思

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

如需打开内存分析器,请按以下步骤操作:

依次点击 View > Tool Windows > Profiler(您也可以点击工具栏中的 Profile 图)。

从 Android Profiler 工具栏中选择要分析的设备和应用进程。如果您已通过 USB 连接设备但系统未列出该设备,请确保您已启用 USB 调试。

点击 MEMORY 时间轴上的任意位置以打开内存分析器。或者,您可以从命令行使用 dumpsys 检查您的应用内存,还可以在 logcat 中查看 GC 事件。

Memory Profiler

许多开发者使用 Memory Profiler,是希望发现和定位内存泄漏问题。在介绍 Memory Profile 如何解决这一问题之前,我想先明确 "内存泄漏" 这一概念。无论您当前是否了解内存泄漏,都将帮助我更好地解释 Memory Profile 的工作原理。

内存泄漏

什么是内存泄漏?

通常我们认为,在运行的程序中,如果一个对象无法访问却仍然占用着内存空间,即该对象造成了内存泄漏。如果您使用过 C 语言或 C++ 的指针,您会很熟悉这个概念。

但是在 Kotlin 和 Java 的世界中,事情有些许不同。因为这两种语言是运行在 Java 虚拟机 (JVM) 中的。在 JVM 中,有个重要的概念,就是垃圾回收 (GC)。当垃圾回收运行时,虚拟机会首先识别 GC Root。GC Root 是一个可以从堆外部访问的对象,它可以是本地变量或运行中的线程等。虚拟机会识别所有可以从 GC Root 访问的对象,它们将会被保留。而其他无法从 GC root 访问的对象,则会被认为是垃圾并回收掉。

内存计算方式

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

图 2. 内存分析器顶部的内存计数图例

内存计数中的类别如下:

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++ 中分配的对象。

如果连接到搭载 Android 7.1 及更低版本的设备,只有在内存分析器连接到您运行的应用时,才开始此分配计数。因此,您开始分析之前分配的任何对象都不会被计入。但是,Android 8.0 及更高版本附带一个设备内置性能剖析工具,该工具可跟踪所有分配,因此,在 Android 8.0 及更高版本上,此数字始终表示您的应用中待处理的 Java 对象总数。

与以前的 Android Monitor 工具中的内存计数相比,新的内存分析器以不同的方式记录您的内存,因此,您的内存使用量现在看上去可能会更高些。内存分析器会监控一些额外的类别,这就增加了总的内存使用量,但如果您仅关心 Java 堆内存,"Java"项的数字应与以前工具中的数值相似。 然而,Java 数字可能与您在 Android Monitor 中看到的数字并非完全相同,这是因为新数字计入了自应用的 Java 堆从 Zygote 派生以来为其分配的所有物理内存页面。因此,它可以准确反映您的应用实际使用了多少物理内存。

注意:使用搭载 Android 8.0(API 级别 26)及更高版本的设备时,Memory Profiler 还会显示应用中的一些误报的原生内存使用量,而这些内存实际上是分析工具使用的。对于大约 100000 个对象,最多会使报告的内存使用量增加 10MB。在 IDE 的未来版本中,这些数字将从您的数据中过滤掉。

查看内存分配情况

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

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

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

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

Activity 内存泄漏检测用法

主要用到Profiler模块:

接下来,我们先使用Profiler工具的Capture heap dump抓取一段内存堆数据:

总结

Profiler工具为了我们能方便查看内存泄漏的地方,专门提供了一个View app heap 分类来报告哪些页面泄漏,同时,我们还可以在里面查看非页面类有没有正常被释放,比如单例,当我们退出某个功能后,手动把单例置为空("销毁"),我们只需在强制GC后抓取一段内存数据查看该对象是否仍在活跃即可。

参考链接如下:

原文链接:https://blog.csdn.net/WPR13005655989/article/details/129945991

原文链接:https://blog.csdn.net/qq_31138209/article/details/139924593

原文链接:https://blog.csdn.net/WPR13005655989/article/details/129945991

原文链接:https://blog.csdn.net/qq_31138209/article/details/139924593

相关推荐
长亭外的少年7 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿10 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神11 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛11 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法12 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter13 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快14 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl14 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
麦田里的守望者江15 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin
Dnelic-15 小时前
解决 Android 单元测试 No tests found for given includes:
android·junit·单元测试·问题记录·自学笔记