内存泄漏和内存溢出是两个概念。
内存泄漏,指的是程序使用过的内存“忘记”归还给系统,造成长时间无谓地占用。
内存溢出,指的是内存被大量的使用后,程序再次去申请内存时,系统已经不能满足其要求的情况。
所以,内存泄露到一定程度就会导致内存溢出。
Java中,内存的回收工作是GC来做的。GC也有软肋:如果持有对象的强引用,GC是无法在内存中回收这个对象的。
绕个远说说几种引用:
- 强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。 - 软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。 - 弱引用(WeakReference)
GC扫描过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。 - 虚引用(PhantomReference)
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
列举经常造成内存泄漏的几种情况:
- static变量
- static activity
public class MyActivity extends BaseActivity {
static Activity mActivity = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = this;
}
}
通常,一个activity对象包含了大量的引用,如果赋值给一个静态变量会使activity脱离系统的管理。被泄漏的activity对象会一直存活在内存中,造成内存泄漏。
- static view
public class MyActivity extends BaseActivity {
static TextView textView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
}
}
- 内部类
内部类使用起来是比较便捷的,但就是这么一点福利也要冒着内存泄漏的风险,因为非静态的内部类会持有外部类的一个隐式引用。
- Thread
public class MyActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doSth();
}
private void doSth() {
new Thread() {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}.start();
}
}
假如新线程执行的任务非常耗时,十天半个月都做不完。在此期间,外部类对象也不能被回收。TimerTask和AsyncTask也会有同样的问题。
- Handler
public class MyActivity extends BaseActivity {
Handler mHanlder = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doSth();
}
private void doSth() {
mHanlder.postDelayed(new Runnable() {
@Override
public void run() {
}
}, Long.MAX_VALUE >> 1);
}
}
Runnable会持有外部类引用,造成内存泄漏。
- Sensor Manager
通过Context.getSystemService(int name)可以获取系统服务。这些服务工作在各自的进程中,帮助应用处理后台任务,处理硬件交互。如果需要使用这些服务,可以注册监听器,这会导致服务持有了Context的引用,如果在Activity销毁的时候没有注销这些监听器,会导致内存泄漏。
public class MyActivity extends BaseActivity implements SensorEventListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerListener();
}
void registerListener() {
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
public void onSensorChanged(SensorEvent event) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
恩,就酱。