1 Memory Profile 简介
Memory Profiler 是 Android Profiler 中的一个组件,它可以帮助你识别内存泄漏和内存溢出,从而导致存根、冻结甚至应用程序崩溃。它显示了应用程序内存使用的实时图,让你捕获堆转储、强制垃圾收集
2 Memory Profile 启动
选择监控进程 : 打开profile界面,选择对应的设备,点击 SESSIONS 面板的加号按钮 , 选择对应设备运行的可监控进程 ;
也可以点击运行按钮右侧的 Profile ‘app’ 按钮 , 进入如下界面 , 前提是该应用时通过 Android Studio 安装的
此时就可以监控内存和cpu的占用情况了
二、 Android Profiler 内存监测相关功能
点击MEMORY模块,可以进入到内存的界面,显示如下:
1、用于强制执行垃圾回收事件的按钮。
2、事件时间轴,显示活动状态、用户输入事件和屏幕旋转事件。
3、用于跳转到实时内存数据的按钮。
4、用于显示不同内存模块占用的内存大小,配合图形查看,内存使用量时间轴,会显示以下内容:
- 一个堆叠图表,显示每个内存类别当前使用多少内存,如左侧的 y 轴以及顶部的彩色键所示。
- 一条虚线,表示分配的对象数,如右侧的 y 轴所示。
- 每个垃圾回收事件的图标。
在 Android 8.0 及更高版本上,系统会一律为可调试的应用启用高级性能剖析。
内存占用中的类别如下:
- 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 及更低版本的设备,只有在 Memory Profile 连接到运行的应用时,才开始此分配计数。因此,开始分析之前分配的任何对象都不会被计入。但是,Android 8.0 及更高版本附带一个设备内置性能剖析工具,该工具可跟踪所有分配,因此,在 Android 8.0 及更高版本上,此数字始终表示应用中待处理的 Java 对象总数。
左侧的列表内容如下:
1、Capture heap dump :捕获堆栈
2、Record native allocations:记录native分配
3、Record Java/Kotlin allocation:记录java/Kotlin分配
三、内存快照分析
1. 保存内存快照 : 查看内存泄漏 , 首先强制 GC 回收一下内存 , 然后 Dump 一份内存快照 ;
我们可以使用已分配对象列表上方的两个菜单来选择要检查的堆以及如何组织数据。从第一个选择的内容,选择要检查的堆:
-
View all heap:当系统未指定堆时;
-
View image heap:系统启动映像,包含启动期间预加载的类。此处的分配保证绝不会移动或消失;
-
View zygote heap:写时复制堆,其中的应用进程是从 Android 系统中派生的;
-
View app heap:我们的应用在其中分配内存的主堆;
第二个选择的内容,选择如何安排分配:
-
Arrange by class:根据类名称对所有分配进行分组。这是默认选项;
-
Arrange by package:根据软件包名称对所有分配进行分组;
-
Arrange by callstack:将所有分配分组到其对应的调用堆栈;
第三个选择的内容
-
Show all classes 显示所有的classes
-
Show activity/fragment Leaks 显示对应的内存泄漏
-
Show project classes 显示项目的
在类列表中,我们可以查看以下信息:
-
Allocations:堆中的分配数;
-
Native Size:此对象类型使用的原生内存总量(以字节为单位)。只有在使用 Android 7.0 及更高版本时,才会看到此列;
-
Shallow Size:此对象类型使用的 Java 内存总量(以字节为单位);
-
Retained Size:为此类的所有实例而保留的内存总大小(以字节为单位);
四、内存泄漏
当出现内存泄漏时,点击 “Leaks”按钮,
选择对应的类名,点击‘References’,根据GC root only的路径进行选择,可以看到引用的路径。
列出的每个实例都包含以下信息:
-
Depth:从任意 GC 根到选定实例的最短跳数;
-
Native Size:原生内存中此实例的大小。 只有在使用 Android 7.0 及更高版本时,才会看到此列;
-
Shallow Size:Java 内存中此实例的大小;
-
Retained Size:此实例所支配内存的大小;
从以上案例可以看出来,是lyricHandler被引用导致了PlayActivity无法被释放。