Memory Profiler是Android Profiler中的一个组件 ,可帮助您识别因内存泄漏和内存抖动导致的卡顿,无响应,甚至crashes。它显示了应用程序内存使用的实时图形,可以捕获堆信息,强制GC以及跟踪内存分配。我们使用Memory Profiler执行以下操作:
在时间轴中寻找可能导致性能问题的不良内存分配模式。
dump Java heap查看在任何给定时间哪些对象正在使用内存。在一段时间内Several heap dumps可以帮助识别内存泄漏。
在正常和极端的用户交互过程中记录内存分配,以确定代码在短时间内分配太多对象或分配泄漏对象的位置。
默认图
打开Memory Profiler,你会看到你的应用程序的内存使用和访问工具的详细时间表,强制垃圾收集,heap dump,并记录内存分配。
标号解析
标号1:强制GC按钮。
标号2:堆内存快照。
标号3:内存分配录制按钮,此功能只出现在Android7.1及更低版本。
标号4:时间轴缩放按钮。
标号5:跳转到实时内存数据显示的按钮。
标号6:event 时间轴,显示activity状态, user input events, and screen rotation events.
标号7:内存使用时间轴。(包含每个内存类别使用多少内存的堆栈图,如左侧的y轴和顶部的颜色键所示;虚线表示分配对象的数量,如右边的y轴所示;每个垃圾收集事件的图标。)
图例
类别解析
Java:从Java或Kotlin代码分配的对象的内存。
Native:从C或C ++代码分配的对象的内存。
Graphics:用于图形缓冲区队列的内存,用于在屏幕上显示像素,包括GL表面,GL纹理等。(请注意,这是与CPU共享的内存,不是专用的GPU内存。)
Stack:您的应用中的native和Java堆栈使用的内存。这通常与您的应用程序运行的线程数有关。
Code:您的应用程序使用代码和资源的内存,如dex字节码,优化或编译的dex代码,.so库和字体。
Other:你的应用程序使用的内存,系统不知道如何分类。
Allocated:您的应用程序分配的Java / Kotlin对象的数量。这不会计算以C或C ++分配的对象。
注
当连接到运行Android 7.1及更低版本的设备时,只有当Memory Profiler连接到正在运行的应用程序时,才会启动此分配计数。因此,在开始分 析之前分配的任何对象都不会被计入。但是,Android 8.0包含一个设备分析工具,可以跟踪所有分配情况,因此这个数字总是表示Android 8.0及更高版本上应用程序中未完成Java对象的总数。
与以前的Android监视器工具的内存计数相比,新的内存分析器以不同的方式记录您的内存,因此您的内存使用似乎更高。Memory Profiler监视一些增加总数的额外类别,但是如果您只关心Java堆内存,那么“Java”数字应该类似于上一个工具的值。
内存分配显示你的内存中的每个对象是如何分配的。具体来说,内存分析器可以显示以下关于对象分配的内容:
分配了什么类型的对象以及它们使用了多少空间。
每个分配的堆栈跟踪,包括哪个线程。
解除分配对象时(仅在使用Android 8.0或更高版本的设备时)。
如果您的设备运行的是Android 8.0或更高版本,则可以随时查看对象分配,如下所示:只需在时间轴上单击并按住,然后拖动以选择要查看分配的区域(如视频1所示)。没有必要开始录制会话,因为Android 8.0和更高版本包括一个设备上的分析工具,不断跟踪你的应用程序的分配。
如果您的设备运行的是Android 7.1或更低版本,请单击Memory Profiler工具栏中的记录内存分配 。在录制期间,Android监控器会跟踪您应用中发生的所有分配情况。完成后,单击 停止录制 (同一按钮;请参阅视频2)查看分配。
检查分配记录,请按照下列步骤操作:
浏览列表以查找具有异常大堆计数并可能泄漏的对象。为帮助查找已知类,请单击“ 类名” 列标题按字母顺序排序。然后点击一个类名。该 实例的查看窗格显示在右侧,显示出类的每个实例。
在“ Instance View”窗格中,单击一个实例。“ Call Stack”选项卡显示在下面,显示实例被分配的位置以及在哪个线程中。
在“ Call Stack”选项卡中,单击任何行以跳转到编辑器中的代码。
heap dump捕获应用程序中的哪些对象正在使用内存。特别是在扩展user session之后,heap dump识别内存泄漏。查看以下内容:
应用分配了哪些类型的对象,以及每个对象的数量。
每个对象使用多少内存。
每个对象的引用都在代码的什么地方。
调用堆栈分配对象的位置。
heap dump时Java内存量可能会暂时增加。这是正常的,因为heap dump发生在与您的应用程序相同的进程,并需要一些内存来收集数据。
字段解析:
Alloc Count:堆中的分配数量。
Native Size:此对象类型使用的本机内存总量(以字节为单位)。此列仅适用于Android 7.0及更高版本。
你会在这里看到一些在Java中分配的对象的内存,因为Android为一些框架类使用本地内存,比如Bitmap。
Shallow Size:此对象类型使用的Java内存总量(以字节为单位)。
Retained Size:由于此类的所有实例而保留的内存总大小(以字节为单位)。
在班级列表顶部,您可以使用左侧的下拉列表在下列堆转储之间切换:
Default heap:当系统没有指定堆时。
App heap:应用程序分配内存的主要堆。
Image heap:系统引导映像,包含在引导期间预加载的类。这里的分配保证不会移动或消失。
Zygote heap:Android系统中的应用程序进程分支的写入时复制堆。
堆中的对象列表按类名排列,默认情况下。您可以使用另一个下拉菜单在以下安排之间切换:
Arrange by class:根据类名称对所有分配进行分组。
Arrange by package:根据包名分组所有分配。
Arrange by callstack:将所有分配分组到相应的调用堆栈中。只有在录制分配时捕获堆转储时,此选项才有效。即使如此,在开始录制之前堆中可能会有一些对象,所以这些分配首先出现,只是按类名称列出。
检查堆,请按照下列步骤操作:
浏览列表以查找具有异常大堆计数并可能泄漏的对象。为帮助查找已知类,请单击“ Class Name” 列标题按字母顺序排序。然后点击一个类名。该 Instance View的查看窗格显示在右侧,显示出类的每个实例。
Instance View单击一个实例。“ References ” 选项卡显示在下方,显示对该对象的每个引用。
在“ References”选项卡中,如果您确定可能正在泄漏内存的引用,请右键单击它并选择“ Go to Instance”。这将从堆转储中选择相应的实例,向您显示其自己的实例数据。
一旦 capture a heap dump,只有在分析器正在运行时,才能在Memory Profiler中查看数据。当您退出分析会话时,会丢失。如果稍后想要保存以供稍后查看,请通过单击时间线下面的工具栏中的Export capture to file导出到HPROF文件。HPROF可以用Android Studio重新打开,如果用其他分析器需要 android_sdk/platform-tools/hprof-conv 转换才可以。
使用Memory Profiler时,应该stress your app code并尝试强制内存泄漏。在应用程序中引发内存泄漏的一种方法是在检查堆之前让它运行一段时间。泄漏可能会溢出到堆中分配的顶部。但是,泄漏越小,运行应用程序以查看它所需的时间就越长。
您还可以通过以下某种方式触发内存泄漏:
在不同的活动状态下,将设备从纵向旋转到横向并再次旋转多次。旋转设备往往会导致应用程序泄漏的 Activity, Context或 View因为系统重新创建对象Activity,如果您的应用程序拥有对这些对象的其他地方的一个参照,系统无法垃圾收集。
在不同的活动状态下切换您的应用程序和另一个应用程序(导航到主屏幕,然后返回到您的应用程序)。
View the Java Heap and Memory Allocations with Memory Profiler