没有用的对象资源任与GC-Root保持可达路径,导致系统无法进行回收。举一个最简单的栗子,我们在 Activity 的 onCreate 函数中注册一个广播接收者,但是在 onDestory 函数中并没有执行反注册,当 Activity 被 finish 掉时,Activity 对象已经走完了自身的生命周期,应该被资源回收释放掉,但由于没有反注册, 此时 Activity 和 GC-Root 间任然有可达路径存在,导致 Activity 虽然被销毁,但是所占用的内存资源却无法被回收掉
1工具
1 静态代码分析工具 —— Lint
2通过AS 的Memory Monitor 生成hprof文件,这些文件是非标准格式的,所以还需要通过MAT生成标准的hrof文件 分析方法有1 Dominator Tree 列出app中所有活动的Activity中引用对象,或者 通过OQL 定位出泄露的对象。内存泄漏猜想
3严苛模式 —— StrictMode
2泄露方式:
1Handler内存泄漏
2
非静态内部类持有外部类的引用 使用不慎会造成内存溢出:非静态内部类引用外部实例,生命周期和外部的引用一样长,而且静态内部类只是调用静态的对象,不能引用实例,泄露:handler的持有
1.当一个Android应用启动的时候,会自动创建一个供应用主线程使用的Looper实例。Looper的主要工作就是一个一个处理消息队列中的消息对象。在Android中,所有Android框架的事件(比如Activity的生命周期方法调用和按钮点击等)都是放入到消息中,然后加入到Looper要处理的消息队列中,由Looper负责一条一条地进行处理。主线程中的Looper生命周期和当前应用一样长。
2.当一个Handler在主线程进行了初始化之后,我们发送一个target为这个Handler的消息到Looper处理的消息队列时,实际上已经发送的消息已经包含了一个Handler实例的引用,只有这样Looper在处理到这条消息时才可以调用Handler#handleMessage(Message)完成消息的正确处理。
3.在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用
解决: 静态外部类+弱引用
3未正确使用Context
4Bitmap对象
5 监听器未关闭
总结:
完成需求功能开发后,再去优化内存泄漏问题;
泄漏源有多处时,核心功能产生的泄漏优先处理,用户使用频繁的功能引起的泄漏优先处理;
处理泄漏避免影响原有的代码逻辑,优化过后最好能够让测试童鞋过一遍相关的功能,避免引入未知的BUG;