内存泄露:说简单点,就是该释放的对象,没有被释放,gc 回收不了
1,java 中的内存泄露
(1)内存分配策略:
静态存储区:方法区
主要存储的是静态数据,全局变量,在程序一开始就已经分配好了,直到程序退出时才会被回收
栈区:保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例
笼统点就是保存变量名
堆区:用来存放动态产生的数据,比如new出来的对象,
(2)java内存管理
String string1 =new String("abc");
其中string1 保存在栈区,new String("abc")保存在堆区
从指针的角度上解释:string1是指向abc这块内容的指针,它自己本身需要有内存保存,这部分保存在栈区。同时,它所指向的内容也需要有内存保存,这部分保存在堆区
(3)java的内存泄露:其实和安卓的内存泄露是一样的,无用对象持续占用内存,而不被gc回收
当string1指向的内容为空时,abc所占用的这部分内存是需要被gc回收的,如果不回收,那就是内存泄露了
2,安卓中的内存泄露,以及解决办法,严重的内存泄露就会导致 OOM 内存溢出,程序奔溃
(1)单例模式:单例对象是一个静态对象,保存在静态存储区,生命周期和整个app的生命周期是一样的
如果,在单例对象中,需要传入了一个activity的context,而此时,activity需要被回收,但是单例对象中的context依然存在,导致activity无法回收
解决的办法:单例对象中的context获取整个app的context
(2)内部类:内部类默认持有外部类的引用
class B{
class A{
private static String C="adsf";
}
}
比如以上情况,当classB对象创建和A创建之后,需要对B对象进行销毁时,因A持有外部类B的引用,同时A对象存在静态变量C(生命周期和app的生命周期是一样的),
此时因为变量C不回收,导致A不回收,A又持有B的引用,最后导致B回收不了
解决办法:将classA 改为静态类,就不会持有外部类的引用了
(3)handler 导致的内存泄露问题
MainActivity{
private Handler handler = new Handler(){
//内部类存在外部类MainActivity的引用
};
}
Hanlder内部 存在looper在不断的轮询处理message,当MainActivity需要被回收时,looper中还存在message未处理或者正在处理,message内部又存在handler的引用
所以,handler不会被回收,从而导致整个MainActivity不被回收
解决的办法:
1, handler改为静态内部类
如果需要同时可以让handler内部存在外部MainActivity的弱引用。
2,在onDestroy中,handler.removeCallbacksAndMessages(null);
private static class MyHandler extends Handler{
private WeakReference context =null;
public MyHandler(Context context){
super();
this.context=new WeakReference(context);
}
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于