Android中内存泄露分类
一、context使用不当导致的内存泄露
根本原因在于,context(比如Activity)是有生命周期的,它被一个更长生命周期的对象所持有,导致了内存泄露。具体分为:
(1)静态context导致的泄露,因为静态变量的生命周期和类是一致的,类只要加载进来就一直在,静态变量保存在方法区的;
一个静态变量,间接引用了context,比如已经让view展示的静态Drawable(我觉得一个成熟的开发者没有这样干的);
(2)单例对象中有变量引用了context导致的泄露
(3)非静态内部类(包括匿名内部类)隐式引用context导致的泄露
a、线程引用外部类对象
b、Handler导致内存泄露问题
Handler采用静态内部类+WeakReference的方式,Activity退出后,等到GC的时候,弱引用的Activity就会被回收掉,但是那些在Activity中通过Handler放到消息队列中的消息还在(如果还没到时间处理),Activity都退出了,这些消息是没有意义了,这种还是有“一些”泄露,因为消息最终肯定会被执行的,我把这种泄露叫“泄露了一段时间”。
所以最好的做法是在Activity的onDestroy的方法中,remove掉所有消息。
特殊说明:Handler使用过程中,内部类默认引用外部类对象导致的泄露,还具体分为两种,一种是内部类handler,另一种是handler发送的Runnable内部类。具体逻辑,大家可以自行思路。
参考:
二、
ThreadLocal用法详解和原理(weakReferenc 和 内存泄露)
Handler导致的内存泄露,我们通过静态内部类和弱引用的方式解决,虽然可能会导致“泄漏一段时间”,但最终还是能保证没有内存泄漏。可是ThreadLocal,官方虽然把key采用弱引用的方式,防止内存泄漏,但是也不能保证百分百的不内存泄漏,原因请看上面的文章,所以最好的办法还是ThreaLocal不用的时候,先remove一下,先把当前线程ThreaLocalMap中存的key value先移除,然后把ThreadLocal的引用置为null,这样ThreadLocal就不会导致内存泄漏了。不过官方建议ThreadLocal 设置成static的,这样也没有释放的必要,也不会有内存泄漏,比如Android Looper中ThreadLocal的使用。
三、使用线程的时候很容易导致内存泄漏,如使用Thread或者AsyncTask,这个网上有很多的说明。如果规范使用线程,可以看看《阿里巴巴Android使用规范》Android(Java)线程使用规范
四、在缓存对象的时候,也可能会导致内存泄漏Glide之ActiveResource