Android 如何做一次内存泄漏大排查 | 您所在的位置:网站首页 › jni内存泄露怎么办 › Android 如何做一次内存泄漏大排查 |
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/112335970 本文出自【赵彦军的博客】 文章目录 前言把内存泄漏的地方找出来leakcanary 状态hprof如何获取 HPROF如何打开 hprof 文件 Heap DumpHeap Dump 是什么?Heap Dump里面有什么? 如何做一次 `Heap Dump` ?如何代码触发 Heap Dump如何手动触发 GCAndroid Profiler指标Heap Dump指标分析对象跟踪策略记录某一段时间的内存分配情况Memory Analyzer(MAT)祝福 前言眼瞅着还有一个月就过年,项目也没有那么忙了,技术老大要求做一做性能优化方面的工作。 而我的任务就是把项目中的内存泄漏撸一遍,然后安排对应的人处理。 说到内存泄漏,我也算是老手了,其实在 2016 年我就写个内存泄漏方面的文章: Android 如何有效的解决内存泄漏的问题 把内存泄漏的地方找出来说干就干,首要的任务就是把内存泄漏的代码揪出来,我选择 leakcanary github 地址:https://github.com/square/leakcanary/ 关于 leakcanary 的介绍,集成步骤,我就不在这里展开讲述了,网上有很多文章,你们自己搜索一下。 我只啰嗦一点: 1、 leakcanary 2.0之后的版本集成不需要初始化集成完成后,把项目跑起来,过一会就会报出来很多内存泄漏的日志。 在 Android Studio logcat 过滤 LeakCanary 就会看到如下: 首先 MainActivity 实例发生内存泄漏 --> 再往上可以看到 MainActivity 泄漏 原因是 MainActivity 里的一个 Lambda 表达式引起的 --> … --> 再往上 看到 MutableLiveData 引起的 --> … --> … 看到这个分析链条,我们就很清楚了,大概率是 MutableLiveData 对象引起的,再结合实际的项目代码,最后发现果然是因为 MainActivity 里的 MutableLiveData 对象没有释放。 特别要注意的是: 纵然 leakcanary 工具很牛逼,但是要想清晰的定位,然后修复内存泄漏,还是要结合实际的项目代码的。 到这里我们基本就完成了 把内存泄漏揪出来 的问题。 leakcanary 状态在上面一部分,我贴了两个图,图中的有很清晰的对象引用链条。leakcanary 对每个对象都标明了泄漏的状态。 Leaking: YES 确定已经泄漏Leaking: UNKNOWN 不确定是否泄漏Leaking: NO 没有泄漏我们在分析 对象引用链条的时候,要特别注意 UNKNOWN 状态,这个状态即有可能是泄漏了,也有可能是没有泄漏,这就需要我们程序要认真的分析项目代码,然后给出结论 hprofleakcanary 在运行的时候,发现内存泄漏了,会把 Java堆快照转储到Android HPROF文件中,方便开发者分析。 如何获取 HPROF方式一:通过 logcat 获取 在 Android Studio 的 logcat 中会输出 hprof 文件地址:
adb pull /storage/emulated/0/Download/leakcanary-com.cootek.crazyreader/2021-01-08_11-21-08_472.hprof ~/DeskTop 方式二:通过客户端可视化页面
正文到这里其实也就结束了。在做内存泄漏排查的时候用到了 AndroidStudio Profiler 工具,里面有很多新的概念和内存指标,下面的内容就是在探究 Profiler 工具如何使用以及各种内存指标所代表的含义 如何打开 hprof 文件方式一:Android studio Profiler 功能打开 用HPROF分析工具,可以检测到泄漏的 Activity Heap Dump 也叫堆转储文件,是一个 Java 进程在某个时间点上的内存快照。Heap Dump 是有着多种类型的。不过总体上 heap dump 在触发快照的时候都保存了 java对象和类的信息。通常在写heap dump文件前会触发一次FullGC,所以heap dump文件中保存的是FullGC后留下的对象信息。 简单说就是: heap dump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况。HeapDump文件是指定时刻的Java堆栈的快照,是一种镜像文件。 Heap Dump里面有什么?一般在 Heap Dump 文件中可以获取到(这仍然取决于heap dump文件的类型)如下信息: 对象信息:类、成员变量、引用值;类信息:类加载器、名称、超类、静态成员;Garbage Collections Roots:JVM可达的对象;线程栈以及本地变量:获取快照时的线程栈信息,以及局部变量的详细信息也就是说我们可以对上面这些内容进行分析。通常可以基于 Heap Dump 分析如下类型的问题: 找出内存泄漏的原因;找出重复引用的jar或类;分析集合的使用;分析类加载器。总而言之我们对 Heap Dump 的分析就是对应用的内存使用进行分析,从而更加合理地使用内存。 如何做一次 Heap Dump ?在前面讲到的,hprof 文件都是 Leakcanary 工具帮我们做的,那我们自己想要自己做一次 Heap Dump ,生成 hprof 文件又该怎么做呢? 其实 AndroidStudio 有现成的工具,只要动动手机就行了。 AndroidStudio --> Profiler --> 点击 + 号 --> 选择设备 --> 选择进程 --> 点击 MEMORY --> 点击 向下的箭头
至此,我们就完成手动 Heap Dump 操作,并且生成 hprof 文件 。我们也可以点击保存按钮,把 hprof 文件保存到桌面,或者发给其他人。 代码其实很简单: try { //指定Hprof文件的名字 var path: String = externalCacheDir?.absolutePath + File.separator + System.currentTimeMillis() + ".hprof" Debug.dumpHprofData(path) } catch (e: Exception) { }生成的文件在 Android/data/app包名/cache/ 目录下: AndroidStudio --> Profiler --> 点击 + 号 --> 选择设备 --> 选择进程 --> 点击 MEMORY --> 点击 像垃圾桶 的图标
官方文档:https://developer.android.com/studio/profile/memory-profiler
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 对象总数。 只有看懂了每个指标,才能更好的分析内存,下面我们分析一下 heap Dump 指标 为了在分析时提高应用性能,内存性能分析器在默认情况下会定期对内存分配进行采样。在运行 API 级别 26 或更高级别的设备上进行测试时,您可以使用 Allocation Tracking 下拉菜单更改此行为。可用选项如下: Full:捕获内存中的所有对象分配。这是 Android Studio 3.2 及更低版本中的默认行为。如果您有一个分配了大量对象的应用,可能会在分析时观察到应用的运行速度明显减慢。Sampled:定期对内存中的对象分配进行采样。这是默认选项,在分析时对应用性能的影响较小。在短时间内分配大量对象的应用仍可能会表现出明显的速度减慢。Off/None:停止跟踪应用的内存分配。![]() Heap Dump 是一个很好用的工具,能够分析内存中所有的对象,但是也是有弊端的,Heap Dump 是全量分析,如果你想分析某一段时间内的内存增量分配情况,该怎么做呢?点击 Record 按钮.
Memory Analyzer 工具,简称:MAT 。 MAT 是 Eclipse 下的一个软件,专门用来分析 Java内存堆。 官方下载地址:https://www.eclipse.org/mat/ 安装完成后,图标如下 MAT可以打开 .hprof , 但是从 AndroidStudio 里面的导出的 .hprof 文件,MAT 是不支持查看的,所以需要转化一下,Android SDK 自带了转化工具。 您可以使用 android_sdk/platform-tools/ 目录中提供的 hprof-conv工具执行此操作。运行包含两个参数(即原始 HPROF 文件和转换后 HPROF 文件的写入位置)的hprof-conv 命令。例如: hprof-conv heap-original.hprof heap-converted.hprof 经过转化过的 .hprof 文件,MAT 就可以打开了。 快过年了,祝大家 2021 事事顺心,万事大吉。新年快乐鸭 !! |
CopyRight 2018-2019 实验室设备网 版权所有 |