java的内存分配
- 静态存储区: 编译时已经分配好内存,在程序整个运行期间都存在,主要存放静态数据和常量
- 栈区:当方法执行时,会在栈区中创建方法内部的局部变量,方法结束后自动释放内存
- 堆区:通常用来存放new出来的对象,由java垃圾回收器回收
内存泄露分析
永远的singleton
由于单例的静态特性,使得它的生命周期和应用的生命周期一样长。当我们使用单例的时候,要注意它内部持有的引用,如Activity(导致Activity不能被回收)
public class Singleton{
private static Singleton singleton;
private Context context;
private Singleton(Context context){
this.context=context;
}
public static Singleton getInstance(Context context){
if(singleton==null){
singletoon=new Singleton(context);
}
return singleton;
}
}
如果该单例中需要一个Context,那么确保不要持有Activity的引用,可以使用Application提供的Context。
让人心塞的handler
handler一般作为Acvivity的非静态内部类被创建,那么他就持有了Activity的引用,当我们发送一个延迟消息的时候,Message持有hanlder的引用,而handler持有Activity的引用,所以,当我们主动调用finish()方法的时候,Activity并不会被回收。而如果我们在Activity中需要引用外部的非static对象,应该通过弱引用传入。
public class DemoActivity extends Activity{
private static final class MyHandler extends Handler{
private final WeakReference<DemoActivity> mActivity;
public MyHandler(DemoActivity activity){
this.mActivity=new WeakReference<DemoActivity>(activity);
}
@override
public void handleMessage(Message msg){
DemoActivity activity=mActivity.get();
if(activity!=null){
//do sonmething
}
}
}
private final MyHandler handler=new MyHandler(this);
}
静态内部类不会持有外部类的引用,推荐使用静态内部类+弱引用,每次使用时注意进行非空判断。
同时,在Activity被销毁时,可以清空MessageQueue中的消息。
匿名内部类/非静态内部类
一般在Activity、Fragment或者View中创建内部类,如果是非静态内部类,则会持有外部类的引用。
而如果这个内部类被异步线程所引用,则很可能导致内存泄露。
public class DemoActivity extends Activity{
private static TestInnerBad testInnerBad=null;
class TestInnerBad{}
@override
public void onCreate(Bundle bundle){
if(testInnerBad==null){
testInnerBad=new TestInnerBad(); //内存泄露
}
Runnable r1=new Runnable(){ //可能内存泄露
@override
public void run(){
}
}
Runnable r2=new MyRunnable();
}
private static class MyRunnable implements Runnable{
@override
public void run(){}
}
}
TestInnerBad是DemoActivity的内部类,持有他的引用,而它又被声明为static,那么他的生命周期就和App一样,那么肯定是造成了DemoActivity无法被正确的回收。对静态类的正确处理方法是---单独抽取出来封装成一个单例。
r1是DemoActivity的匿名内部类,他持有DemoActivity的引用,而如果r1被传入到一个异步线程中,则很可能造成内存泄露。
集合对象的清除
如果这个集合是static,那么该集合会一直持有传入对象的引用,一般要在Activity、Fragment被销毁时将集合清空。
网友评论