内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况
内存溢出(Out Of Memory) 就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
OOM产生的原因:1.内存泄漏 2.频繁申请内存得不到及时的回收
减少OOM的概率:1.尽可能少的发生内存泄漏 2.尽可能不在循环中申请内存 3.尽可能不在调用次数多的函数中申请内存
内存泄漏(Memory Leak):产生的原因:一个长生命周期的对象持有一个短生命周期对象的引用,通俗讲就是该回收的对象,因为引用问题没有被回收,最终会产生OOM
内存抖动(Memory Churn)
概念:在短时间内反复地发生内存增长和回收
问题:内存抖动可能导致程序卡顿甚至OOM内存溢出。
卡顿原因:当gc回收内存时,会使当前的工作线程暂停,如果多次内存回收行为集中在短时间内爆发,,就有可能造成卡顿
gc检测垃圾对象主要有两种算法:引用计数法和可达性分析法
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024 /1024);
Log.d("TAG", "Max memory is " + maxMemory+"MB");
1.单例引起的内存泄漏
原因:由于单例的静态特性导致它的生命周期和整个应用的生命周期一样长,如果有对象已经不再使用了,但又却被单例持有引用,那么就会导致这个对象就没办法被回收,从而导致内存泄漏。
// 使用了单例模式
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
2.非静态内部类创建静态实例引起的内存泄漏
由于非静态内部类会默认持有外部类的引用,如果我们在外部类中去创建这个内部类对象,当频繁打开关闭Activity,会导致重复创建对象,造成资源的浪费,为了避免这个问题我们一般会把这个实例设置为静态,这样虽然解决了重复创建实例,但是会引发出另一个问题,就是静态成员变量它的生命周期是和应用的生命周期一样长的,然而这个静态成员变量又持有该Activity的引用,所以导致这个Activity销毁的时候,对象也是无法被回收的。
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (mResource == null) {
mResource = new TestResource();
}
//...
}
class TestResource {
//...
}
}
我们来分析问题所在:其实这个和上面单例对象的内容泄漏问题是一样的,由于静态对象持有Activity的引用,导致Activity没办法被回收。
MyHandler myHandler = new MyHandler(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
@Override
public void run() {
myHandler.sendMessage(Message.obtain());
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
//移除对应的Runnable或者是Message
// mHandler.removeCallbacks(runnable);
// mHandler.removeMessages(what);
mHandler.removeCallbacksAndMessages(null);
}
private static class MyHandler extends Handler {
private WeakReference mActivity;
public MyHandler(Activity activity) {
mActivity = new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
if (mActivity.get() == null) {
return;
}
//to do something..
}
};
4.WebView引起的内存泄露
关于WebView的内存泄漏,这是个绝对的大大大大大坑!不同版本都存在着不同版本的问题,这里我只能给出我平时的处理方法,可能不同机型上存在的差异,只能靠积累了。