Android内存泄漏分析
概述
Android内存泄漏,也就是我们常说的OOM(out of memory)
,OOM
的后果大家都知道,严重影响APP的体验,轻则卡顿,重则闪退。而且内存泄漏在低端机上一般都会伴随着ANR
,所以一定要重视它。
造成内存泄漏的常见因素有:
- IO操作
- Bitmap
- Context
- 单例持有引用
- Service
- BroadcastReceiver
- ContentObserver
- Handler
- Thread
分析方法
分析内存泄漏的常用方法:
- StrictMode, 在
Application
的onCreate
中添加StrictMode
代码块 - Leakcanary,引用
Leakcanary
库(常规手段,仅供参与,不应完全依赖这个库) - monkey,模拟用户点击操作,检查是否出现泄漏(推荐,最有效的方法)
- adb命令手动触发
adb shell dumpsys meminfo packagename -d
- Android Studio Memory Profiler,
Android Studio
自带的分析工具,已经非常好用了 - MAT,终极神器,内存分析绕不开的话题(
Android Studio
搞不定就靠它了)
解决方案
-
Context 如果大家收集过内存泄漏的崩溃日志,会发现大量错误都是由
Context
和Handler
造成。 因为我们开发中会大量用到Context
引用,而Context
在Application
,Activity
,Service
之类的地方会有自己的实例,而Activity
和Service
会因为生命周期的原因导致Context
实例被回收,如果你继续使用其引用就会因为弱引用问题导致错误出现。Context
的引用也常见于单例模式。 所以建议大家尽可能使用Application
的Context
。 -
Bitmap Bitmap的问题一般是因为没有对使用的图片及时释放所致。 图片一般因为体积问题,会导致占用比较多的内存 解决方案:就是在
Activity
的onDestroy()
中及时回收内存。 -
IO操作 FileOutputStream()未关闭,IO流忘记关闭 解决方案:及时关闭IO流,避免泄露
-
Handler泄漏 由于Activity已经关闭,Handler任务还未执行完成,其引用了Activity的实例导致内存泄露 解决方案:在Activity的onDestroy()方法回收Handler
-
异步线程泄露 一般发生在线程执行耗时操作时,如下载,此时Activity关闭后,由于其被异步线程引用,导致无法被正常回收,从而内存泄露 解决方案:把线程作为对象提取出来,在Activity的onDestroy()方法阻塞线程
-
静态成员变量 开发中会定义许多
static
变量,如果有大量的静态变量定义,并有引用资源,一定要在onDestroy
或其他地方及时释放(把变量置空即可)