性能优化中使用Profiler进行内存泄露的排查及解决方式

文章目录

  • 一、前言
  • 二、内存泄露的排查方式
  • 三、参考链接

一、前言

对于常规意义上的线程使用要及时关闭,数据库用完要及时关闭,数据用完要及时清空等等这里不再赘述,但是在开发中总会有不熟悉的api,开发进度过快,开发人员粗心等等原因导致内存泄露。可以使用leakcanary(参考链接:https://square.github.io/leakcanary/)内存检测处理,或者使用lint(参考链接:https://developer.android.google.cn/studio/write/lint?hl=zh-cn)静态代码检测后=,或者开启严格模式StrictMode(参考链接:https://developer.android.google.cn/reference/android/os/StrictMode),或者使用Profiler(参考链接:https://developer.android.com/studio/profile/android-profiler?hl=zh-cn)等等不同的方式进行内存泄露的检查。本文记录Profiler进行内存泄露检查的使用方式。

需要注意的是本篇文章采用了Android Studio新版的UI进行操作,具体开启方式为Preferences->Appearance & Behavior ->New UI 。然后勾选Enable new UI并重启Android Studio。开发工具版本为

Android Studio Giraffe | 2022.3.1 Patch 4
Build #AI-223.8836.35.2231.11090377, built on November 14, 2023
Runtime version: 17.0.6+0-17.0.6b829.9-10027231 aarch64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.

目前为最新版本开发工具。
测试工具为红米K60,版本为Android13
如需打开 Profiler 窗口,请依次选择 View > Tool Windows > Profiler,或点击工具栏中的 Profile 图标 在这里插入图片描述

二、内存泄露的排查方式

当通过正常启动应用或者通过如下方式启动应用后
性能优化中使用Profiler进行内存泄露的排查及解决方式_第1张图片
会看到如下页面性能优化中使用Profiler进行内存泄露的排查及解决方式_第2张图片
然后选择Memory选项卡进行双击打开,会看到如下页面
性能优化中使用Profiler进行内存泄露的排查及解决方式_第3张图片
选择Capture heap dump。然后点击Record进行录制需要的功能。这个功能录制完会自动停止,然后停止后的页面如下(这个会自动停止好像跟之前的不太一样,不知道是不是升级后的改动)
性能优化中使用Profiler进行内存泄露的排查及解决方式_第4张图片
可以看到最上层有Leaks的标志,表示内存泄漏数量。点击该位置后可以查看内存泄漏的位置
性能优化中使用Profiler进行内存泄露的排查及解决方式_第5张图片
选择第一个内存泄漏的类双击后,然后保持和如图一直都页面,可以看到内存泄漏路径
性能优化中使用Profiler进行内存泄露的排查及解决方式_第6张图片
有的信息比较浅显就能看出问题,有的则不能,比如第一个问题,暂时不知道该如何去排查问题。
而第二个类属于第三方库io.github.luoqqsh:immersionbar:3.1.0。查看使用方式时候发现其使用方式为

ImmersionBar.with(this).init()

该方式最终将activity持有在map集合里面,由于声明对象为静态类型,所以导致无法释放。暂时这个版本的库没法解决该问题。
第三个类的问题截图如下:
性能优化中使用Profiler进行内存泄露的排查及解决方式_第7张图片
这里很好理解就是一个adListener里面的使用不当导致内存泄漏。代码如下
性能优化中使用Profiler进行内存泄露的排查及解决方式_第8张图片
可以看到在异步加载结束后会更新View,但是加载结束后有可能页面销毁了,但是这里还持有context对象,就会导致内存泄漏。
第四个问题的截图如下:
性能优化中使用Profiler进行内存泄露的排查及解决方式_第9张图片
没什么有太大价值的信息,只能看出是Fragment添加的时候有问题了,然后查看源码看看有没有添加Fragment的操作,好在源码简单,这是一个加载页面,只有一个fragment在里面添加了。
性能优化中使用Profiler进行内存泄露的排查及解决方式_第10张图片
可以看出这个类跟内存泄漏的第五个类是一样的,所以是GoogleNativeInsertAd1Fragment的内存泄漏导致了ScanningFragment的泄漏。查看第五个类的问题
性能优化中使用Profiler进行内存泄露的排查及解决方式_第11张图片
这里可以看出问题出在了NativeAdView(该控件属于admob的控件)上面,所以是这个控件使用不当导致的问题,顺便注意观察下整个调用链,会发现,这个调用链的顺序是从出现问题的地方逐步往外掉用,也就是说GoogleNativeInsertAd1Fragment中的控件导致了这个类泄漏,然后又引发了ScanningFragment的问题,最终导致了Activity的泄漏(这个节点未展开)。
至于最后一个的问题如下:
性能优化中使用Profiler进行内存泄露的排查及解决方式_第12张图片
ReportFragment属于系统类还是隐藏的,不过这种问题也好解决,既然是系统类,那么一定有人已经遇见过了,直接网络搜索一下即可,如下例子:
Android 12原生系统居然有内存泄露隐患?
不过本文不再赘述该问题的解决方式,仅提供一个思路。本文的问题是为如何解决提供一个思路。每个项目逻辑不一样,所以泄漏方式也不一样。能做的只能尽可能去处理这些问题

三、参考链接

  1. 应用性能指南
  2. StrictMode
  3. Android Profiler

你可能感兴趣的:(性能优化,性能优化)