聊聊内存泄漏

内存泄漏场景

Handler的错误使用

Handler是开发中异步处理最常使用到的工具之一,但是如果错误地使用Handler 也极容易产生内存泄漏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MainActivity extends AppCompatActivity {

private final Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//doSomething
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

myHandler.postDelayed(new Runnable() {
@Override
public void run() {
//doSomething
}
},60*10*1000);
}
}

怎么样,看起来是不是合情合理,但是其中隐藏着一个重要的隐患,当我们创建出一个Handler 的时候,代码中的mHandler为Handler 的非静态内部类的实例,所以mHandler 持有对外部类,即Activity 的引用。并且Handler 中的Looper不断轮询消息队列中的message,message 又持有mHandler的引用,但mHandler这玩意儿又持有Activity 的引用,所以这下倒好,因为你一个message 导致我整个Activity都无法被回收,你说气人不气人。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class MainActivity extends AppCompatActivity {

private final MyHandler mHandler = new MyHandler(this);

private static Runnable sRunnable = new Runnable() {
@Override
public void run() {
//doSomething
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler.postDelayed(sRunnable, 60 * 10);

this.finish();
}

private static class MyHandler extends Handler {

private final WeakReference<MainActivity> mActivity;

public MyHandler(MainActivity activity) {
this.mActivity = new WeakReference<MainActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();

if (activity != null) {
//doSomething
}

}
}
}

资源没有及时关闭

在开发中,例如Cursor、File、IOStream等资源在使用后要及时进行关闭,避免造成内存的浪费。
TypedArray、Bitmap等要及时进行recycle
EventBus 、BroadcastReceiver注册后避免重复注册,使用后及时销毁

Java中的四中引用方式的区别

强引用

只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。

软引用

软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。因此,这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。

弱引用

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示

虚引用

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

要注意的是,虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

您的支持是我原创的动力