android内存泄露-总结

1.GC root:

1、  Class:由系统的类加载器加载的类对象

2、  Static Fields

3、  Thread:活着的线程

4、  Stack Local: java方法的局部变量或参数

5、  JNI Local: JNI方法中的局部引用

6、  JNI Global: 全局的JNI引用

7、  Monitor used: 用于同步的监控对象

8、Help by VM: 用于JVM特殊目的由GC保留的对象

 

 

 

 

 

 

 

 

每个应用最大可使用的堆内存受到Android系统的限制:getMemoryClass()

2.context内存泄露

 1、如果一个类持有Context对象的强引用,就需要检查其生存周期是否比Context对象更长。否则就可能发生Context泄漏。

 2、View持有其创建所在Context对象的引用,如果将View对象传递给其它生存周期比View所在Context更长的强引用,就可能会引起内存泄漏。

例如View#setTag(int, Object)的内存泄漏https://code.google.com/p/android/issues/detail?id=18273

 3、把Context对象赋给static变量。

避免Context对象泄漏Checklist

      1、检查所有持有对Context对象强引用的对象的生命周期是否超出其所持有的Context对象的生命周期。

      2、检查有没有把View传出到View所在Context之外的地方,如果有的话就需要检查生命周期。

      3、工具类中最好不要有Context成员变量,尽量在调用函数时直接通过调用参数传入。如果必须有Context成员变量时,可以考虑使用WeakReference来引用Context对象。

      4、View持有其创建所在Context对象的引用,如果将View对象传递给其它生存周期比View所在Context更长的强引用,就可能会引起内存泄漏。

      5、  检查把Context或者View对象赋给static变量的地方,看是否有Context泄漏。

      6、检查所有把View放入容器类的地方(特别是static容器类),看是否有内存泄漏。7、使用WeakHashMap也需要注意有没有value-key的引用。

      7、尽量使用ApplicationContext。

 

 

 

 

 

 

 

 

 

 

 

 

3.handler泄露

发送到Handler的Message实际上是加入到了主线程的消息队列等待处理,每一个Message持有其目标Handler的强引用。

如我们通常使用的匿名内部类Handler

Handler mHandler = new Handler() {
    @Override
    public voidhandleMessage(Message msg) {
       mImageView.setImageBitmap(mBitmap);
    }
}

 

上面是一段简单的Handler的使用。当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用,因为View会依附着一个Activity。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。

当然,应为是Handler对外部持有引用的原因,我们就可以将Activity设置为一个弱引用,在不必要的时候,不再执行内部方法。

publicclass WeakRefHandler extends Handler
{
    WeakReference<Context> mWeakContext;
 
    public WeakRefHandler(Context context)
    {
        mWeakContext = newWeakReference<Context>(context);
    }
 
    @Override
    public void handleMessage(Message msg)
    {
        if((mWeakContext.get() instanceofActivity )&& ((Activity)mWeakContext.get()).isFinishing())
                return ;
        if(mWeakContext==null){
            return ;
        }
        super.handleMessage(msg);
    }
}

 

 

 

 

 

posted @ 2015-10-22 15:15  我在途中  阅读(317)  评论(0编辑  收藏  举报