android 内存泄漏总结
前言
内存泄漏很危险。轻则卡顿,重则oom。
这种东西写代码的时候注意一下就能避免90%的内存泄漏,
只要写代码的时候遇到想一下你就可以避免了,免得后面为了找内存泄漏各种排查,得不尝试!!
最后会总结一下常见的内存泄漏。
导致内存泄漏的原因
总结来说就是:
本该被jvm回收的生命周期短对象却被生命生命周期长的对象直接或间接的所持有导致短对象无法释放。有种藕断丝连的感觉,哈哈...
排查之法-MAT(MemoryAnalyzerTools)
MAT 是一个根据堆的内存信息检测内存对象之间的引用链的关系,根据这个关系我们就可以知道哪些对象内存泄漏了。具体的操作流程网上有很多,这里就不多写了。
排查之法-LeakCanary
LeakCanary是一个检测内存泄露的开源类库,地址:
https://github.com/square/leakcanary
常见的内存泄漏
- 单例造成的内存泄漏,一般是传入的是Context的问题,解决方法:传入 Application 的 Context。
- 匿名内部类/非静态内部类和异步线程造成的内存泄漏,解决方法:静态内部类,静态内部类中使用弱引用来引用外部类的成员变量。
- 避免使用 static 成员变量,它的生命周期和应用的生命周期一样长。
- 资源未关闭造成的内存泄漏,比如:BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
- bitmap的使用问题:加载可以使用色彩模式为rgb565的方式节省内存的开销。释放时调用recyle()方法因为加载Bitmap对象的内存空间:java+c 两部分内存,调用recyle()是释放c内存的空间。
- handler造成的内存泄漏,因为handler的生命周期和activity或者view的生命周期是不一样的,它属于Thread-Local型的,很容易导致无法正确释放。关系:Handler、Message和MessageQueue都是相互关联在一起的,如果Handler发送的Message延时处理,则该Message及发送它的 Handler对象将被线程 MessageQueue一直持有。那么持有Handler的对象(view/activity)就泄漏了。