1,什么是内存泄漏;
2,内存泄漏与内存溢出的区别与关系;
3,常见内存泄漏情况
4,内存泄漏分析工具;
1,内存泄漏(Memory Leak)
是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。通俗一点讲就是不使用或用完的内存,因为某些原因无法回收,造成的一种内存浪费;
2,内存泄漏与内存溢出的区别与关系
内存泄漏是指内存存在于不该存在的地方(没用的地方), 内存溢出是指内存占用达到最大值,当需要分配内存时,已经没有内存可以分配了。其实就是内存的分配超出最大阀值,导致了一种异常。最明显的地方就是报错,APP奔溃并报outofMemory内存溢出多数在处理图片比如操作BitMap时出现。内存的溢出是内存分配达到了最大值,而内存泄漏是无用内存充斥了内存堆;因此内存泄漏是导致内存溢出的元凶之一。
3,常见内存泄漏情况
3.1 adapter没有使用缓存的convertview(listview);
3.2 bitmap对象没有被 recycle()掉;
3.3 context使用不正确,不要对activity context保持长生命周期的引用,竟可能使用applicationcontext代替 context的地方进行替换;
3.4 数据库的 cursor必须手动的关闭,流对象的关闭、webview的销毁;
3.5 注册了系统的服务,但onDestory未注销,比如调用了register方法一般都要在ondestroy中调用unregister方法;
3.6 handler泄漏 handler.removeCallbacksAndMessages(null);
3.7 线程造成的内存泄漏 尽量的使用静态内部类并在Activity销毁时候也应该取消相应的任务AsyncTask:cancel(),避免任务在后台执行浪费资源;
3.8 使用了属性动画或循环动画,在Activity中使用了属性循环动画,在onDestroy()方法中未正确停止动画;
3.9 集合中的一些方法的错误使用,map对象只是put,而无remove操作等等;
3.10 单例造成的内存泄露;
3.11 Timer和TimerTask导致内存泄露,当我们Activity
销毁的时,有可能Timer
还在继续等待执行TimerTask
,它持有Activity的引用不能被回收,因此当我们Activity销毁的时候要立即cancel
掉Timer
和TimerTask
,以避免发生内存泄漏。
4,内存泄漏分析工具
4.1 LeakCanary 是Square公司专门为android弄的,检测内存泄露的工具,这个工具使用很简单,在mudule的build.gradle中添加
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.2'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
// Optional, if you use support library fragments:
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.2'
}
然后在自定义的application中初始化一下就ok
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if(LeakCanary.isInAnalyzerProcess(this)) {
return;
}
LeakCanary.install(this);
}
}
运行代码当有内存泄漏时系统会发送通知,如下
点击查看具体信息
LeakCanary 的核心流程原理如下
判定是否回收(KeyedWeakReference是否存在该引用), Y -> 退出, N -> 向下执行
手动触发GC
判定是否回收, Y -> 退出, N-> 向下执行
两次未被回收,则分析引用情况:
1) humpHeap : 这个方法是生成一个文件,来保存内存分析信息
2) analyze: 执行分析
4.2 MAT(Memory Analyzer Tools)是一个 Eclipse 插件,它是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。MAT是Eclipse的一个插件,而现在android开发很少用到Eclipse了,所以这里就不做过多的介绍。