内存泄漏的几种情况

在Java中内部类的定义与使用一般为成员内部类与匿名内部类,他们的对象都会隐式持有外部类对象的引用,影响外部类对象的回收。

GC只会回收没有被引用或者根集不可到达的对象(取决于GC算法),内部类在生命周期内始终持有外部类的对象的引用,造成外部类的对象始终不满足GC的回收条件,反映在内存上就是内存泄露。(如,Android中Activity的内存泄露)

解决方案为

1.将内部类定义为static

2.用static的变量引用匿名内部类的实例

1.成员内部类
/**
 * 成员内部类
 */
public class Outer {
    private int outer = 1;
 
    class Inner {
        public void show() {
            System.out.println("outer =" + outer);
        }
    }
 
    public static void main(String[] args) {
        Outer.Inner in = new Outer().new Inner();
        in.show();
 
    }
 
}
 
2.方法内部类
/**
 * 方法内部类
 * 
 */
public class Outer2 {
    private int outer = 1;
 
    public void showOut() {
 
        class Inner {
            public void show() {
                System.out.println("outer =" + outer);
            }
        }
        new Inner().show();
    }
 
    public static void main(String[] args) {
        Outer2 in = new Outer2();
        in.showOut();
 
    }
}
防止Handler引起内存泄漏:
方法一:通过程序逻辑进行保护:

(1)在关闭Activity时停掉对应的后台线程。线程停止就相当于切断了Handle和外部链接的线,Activity自然会在合适的时候被回收。

(2)如果Handler是被delay的Message持有了引用,那就使用Handler的removeCallbacks()方法将消息对象从消息队列移除即可。

方法二:将Handler声明为静态类,静态类不持有外部类的对象,所以Activity可以被随意回收。此处使用了弱引用WeakReference,也就是说当在内存不足时,系统会销毁弱/回收引用引用的对象,从而达到优化内存的目的。优化后代码如下:

public abstract class WeakHandler extends Handler {

    protected WeakReference reference;

    //创建子线程Handler使用的构造器
    public WeakHandler(Looper looper, T reference) {
        super(looper);
        this.reference = new WeakReference<>(reference);
    }

    //创建主线程Handler使用的构造器
    public WeakHandler(T reference) {
        this.reference = new WeakReference<>(reference);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        T t = reference.get();
        if (t == null)
            return;
        handleMessage(t, msg);
    }

    protected abstract void handleMessage(T t, Message message);

}
上述代码,我们使用了泛型,这个泛型就是我们之前说的当前类,同时提供了两种构造器,这样不管我们是创建主线程还是非主线程Handler对象时,都不会造成内存泄漏了。
 

你可能感兴趣的:(编程)