Android内存泄露分析以及处理
2017-02-28 10:34
211 查看
基础知识:
java的内存分配
静态存储区:编译时就分配好,在程序整个运行期间都存在。它主要存放静态数据和常量;
栈区:当方法执行时,会在栈区内存中创建方法体内部的局部变量,方法结束后自动释放内存;
堆区:通常用来存放new出来的对象。由java垃圾回收期回收。
四种引用类型的介绍:
强引用(StrongReference):JVM 宁可抛出 OOM ,也不会让 GC 回收具有强引用的对象;
软引用(SoftReference):只有在内存空间不足时,才会被回的对象;
弱引用(WeakReference):在 GC 时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,
都会回收它的内存;
虚引用(PhantomReference):任何时候都可以被GC回收,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,
就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否存在该对象的虚引用,来了解这个对象是否将要被回收。可以用来作为GC回收Object的标志。
内存泄露检测工具
1. MAT(Memory Analyzer Tool),下载地址:
http://www.eclipse.org/mat/downloads.php
2. 强大的开源内存检测工具 LeakCanary。
leakcanary 是一个开源项目,一个内存泄露自动检测工具,是著名的 GitHub开源组织Square贡献的,它的主要优势就在于自动化过早的发觉内存泄露、配置简单、抓取贴心,缺点在于还存在一些bug,不过正常使用百分之九十情况是OK的,其核心原理与MAT工具类似。
因为配置十分简单,只需要几句话就好!!!这里就不多说了,大家可以看官方文档:
https://github.com/square/leakcanary 1.在使用单例模式时,如果我们传入的Context是Activity的Conetxt,当这个对应的Activity退出时,
由于该Context的引用被单例对象所持有,其生命周期等于整个应用的生命周期,所以当前Activity退
出时它的内存并不会回收,所以会造成内存泄露
code:
2.Handler使用不当造成的内存泄露
Handler造成的内存泄露在Android开发中是最常见的,我们知道,Handler,Message以及MessageQuene是相
互关联在一起的,万一Handler发送的Message未被处理,则该Message以及发送它的Handler对象都会一直
被MessageQuene持有。
可以通过弱引用和static内部类来防止内存泄露
综述:推荐使用静态内部类+弱引用 WeakReference 这种方式,但要注意每次使用前判空。
这里再提下java的几种引用类型:StrongReference,SoftReference,WeakReference 和 PhatomReference:
回收时机 级别用途生存时间
StrongReference 绝不强引用 对象的一般状态JVM停止运行时终止
SoftReference
内存不足时 软引用
联合ReferenceQuene构造的有效期短/占内存大/声明周期长的对象的二级高速缓冲器(内存不足时清空)内存不足时终止
WeakReference
在垃圾回收时 弱引用 联合ReferenceQuene构造的有效期短/占内存大/声明周期长的对象的一级高速缓冲器(系统发生gc则清空)gc运行后终止
PhatomReference 在垃圾回收时虚引用联合ReferenceQuene来跟踪对象被gc回收的活动gc运行后终止
继续回到主题。前面所说的,创建一个 静态Handler内部类,然后对 Handler 持有的对象使用弱引用,这样在回收时也可以回收 Handler 持有的对象,
但是这样做虽然避免了 Activity 泄漏,不过 Looper 线程的消息队列中还是可能会有待处理的消息,所以我们在 Activity 的 Destroy 时或者 Stop
时应该移除消息队列 MessageQueue 中的消息。
java的内存分配
静态存储区:编译时就分配好,在程序整个运行期间都存在。它主要存放静态数据和常量;
栈区:当方法执行时,会在栈区内存中创建方法体内部的局部变量,方法结束后自动释放内存;
堆区:通常用来存放new出来的对象。由java垃圾回收期回收。
四种引用类型的介绍:
强引用(StrongReference):JVM 宁可抛出 OOM ,也不会让 GC 回收具有强引用的对象;
软引用(SoftReference):只有在内存空间不足时,才会被回的对象;
弱引用(WeakReference):在 GC 时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,
都会回收它的内存;
虚引用(PhantomReference):任何时候都可以被GC回收,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,
就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否存在该对象的虚引用,来了解这个对象是否将要被回收。可以用来作为GC回收Object的标志。
内存泄露检测工具
1. MAT(Memory Analyzer Tool),下载地址:
http://www.eclipse.org/mat/downloads.php
2. 强大的开源内存检测工具 LeakCanary。
leakcanary 是一个开源项目,一个内存泄露自动检测工具,是著名的 GitHub开源组织Square贡献的,它的主要优势就在于自动化过早的发觉内存泄露、配置简单、抓取贴心,缺点在于还存在一些bug,不过正常使用百分之九十情况是OK的,其核心原理与MAT工具类似。
因为配置十分简单,只需要几句话就好!!!这里就不多说了,大家可以看官方文档:
https://github.com/square/leakcanary 1.在使用单例模式时,如果我们传入的Context是Activity的Conetxt,当这个对应的Activity退出时,
由于该Context的引用被单例对象所持有,其生命周期等于整个应用的生命周期,所以当前Activity退
出时它的内存并不会回收,所以会造成内存泄露
code:
public class SingleDemo{ private static SingleDemo mSingleDemo; private Context mConetxt; private SingleDemo(Context context){ //获取Application的Context避免有泄露 this.mContext=context.getApplicationContext(); } private static SingleDemo getInstance(Context context){ if(mSingleDemo == null){ mSingleDemo=new SingleDemo(); } return mSingleDemo; } }
2.Handler使用不当造成的内存泄露
Handler造成的内存泄露在Android开发中是最常见的,我们知道,Handler,Message以及MessageQuene是相
互关联在一起的,万一Handler发送的Message未被处理,则该Message以及发送它的Handler对象都会一直
被MessageQuene持有。
可以通过弱引用和static内部类来防止内存泄露
public class HandlerActivity extends AppCompatActivity{ //声明为静态的内部类,因为非静态内部类会持有外部类的引用,有可能会造成内存泄露 //声明为静态内部类后,其存活期就与activity的生命周期无关了 private static final class MyHandler extends Handler{ //不过倘若用到 Context 等外部类的 非static 对象,还是应该通过弱引用传入 private final WeakReference<HandlerActivity> mActivity; @Override public void onHandlerMessage(Message msg){ super(msg); HandlerActivity handlerActivity=mActivity.getActivity(); if(handlerActivity!=null){ //do something... } } } private MyHandler mMyhandler=new MyHandler(this); //匿名的静态内部类绝不会持有外部类的引用 private static final Runnable RUNNABLE=new Runnable(){ @Override public void run(){} } protect void onCreate(Bundle saveInstanceStates){ super.onCreate(saveInstanceStates); setContentView(R.layout.activity_main); mMyhandler.postDelayed(RUNNABLE,500); } }
综述:推荐使用静态内部类+弱引用 WeakReference 这种方式,但要注意每次使用前判空。
这里再提下java的几种引用类型:StrongReference,SoftReference,WeakReference 和 PhatomReference:
回收时机 级别用途生存时间
StrongReference 绝不强引用 对象的一般状态JVM停止运行时终止
SoftReference
内存不足时 软引用
联合ReferenceQuene构造的有效期短/占内存大/声明周期长的对象的二级高速缓冲器(内存不足时清空)内存不足时终止
WeakReference
在垃圾回收时 弱引用 联合ReferenceQuene构造的有效期短/占内存大/声明周期长的对象的一级高速缓冲器(系统发生gc则清空)gc运行后终止
PhatomReference 在垃圾回收时虚引用联合ReferenceQuene来跟踪对象被gc回收的活动gc运行后终止
继续回到主题。前面所说的,创建一个 静态Handler内部类,然后对 Handler 持有的对象使用弱引用,这样在回收时也可以回收 Handler 持有的对象,
但是这样做虽然避免了 Activity 泄漏,不过 Looper 线程的消息队列中还是可能会有待处理的消息,所以我们在 Activity 的 Destroy 时或者 Stop
时应该移除消息队列 MessageQueue 中的消息。
@Override protected void onDestory(){ super(); mMyhandler.removeCallBacksAndMessages(Object token); }
相关文章推荐
- Android应用内存泄露分析以及优化方案
- android中事件的分析(触发以及分发处理)
- Android内存泄露分析以及优化方案
- Android中Handler的消息处理机制以及源码分析
- Android中Preference的使用以及监听事件分析处理流程
- Android2.2 Vold 分析-(四)---Vold 消息接收及挂载/卸载处理部分分析
- Android事件处理分析
- Android事件处理分析
- Android 软件安装程序(*.apk)的结构分析、反编译以及汉化
- 【Android游戏开发之十】(优化处理)详细剖析Android Traceview 效率检视工具!分析程序运行速度!并讲解两种创建SDcard方式!
- Android事件处理分析+Android事件处理 +Android输入事件流程
- Android事件处理分析
- Android 软件安装程序(*.apk)的结构分析、反编译以及汉化 (12-24 01:22)
- 【Android游戏开发之九】(细节处理)触屏事件中的Bug解决方案以及禁止横屏和竖屏切换!
- 【Android游戏开发之九】(细节处理)触屏事件中的Bug解决方案以及禁止横屏和竖屏切换!
- Android事件处理分析+Android事件处理 +Android输入事件流程
- Android中AVD的使用以及错误处理方法
- Android事件处理分析
- Android 软件安装程序(*.apk)的结构分析、反编译以及汉化
- android中事件的处理以及应该注意的问题