内存泄漏简记

2018-03-19  本文已影响11人  清明捉鬼
前言

经常有人将内存泄漏内存溢出做区别,其实也是有道理的,毕竟不知道的人根本不知道这两者是啥,又都有“内存”呵呵呵(这里不要光他两比而忘记了内存抖动)。
Android泄漏其实需要结合一张图来看,Java判断对象是否可以回收使用的而是可达性分析算法。
在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的。这个算法的基本思路就是通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。

图片.png

在Java语言里,可作为GC Roots对象的包括如下几种:
a.虚拟机栈(栈桢中的本地变量表)中的引用的对象
b.方法区中的类静态属性引用的对象
c.方法区中的常量引用的对象
d.本地方法栈中JNI的引用的对象

导致泄漏的有:
public static void showToast(Context context,String content) {
        if (toast == null) {
            toast = Toast.makeText(context.getApplicationContext(),content,Toast.LENGTH_SHORT);
        } else {
            toast.setText(content);
        }
        toast.show();
    }

不管是匿名内部类还是“有名”内部类,如果其直接使用外部类任何变量的话,将会持有外部类引用,这样就可能导致外部类无法销毁,譬如回调方法

//A类中
final TextView tvA=find.....
B.getInstance().setOnClickListener(new onClickListener{
  @overide
public viod onClick(){
      tvA.setText("xxx")
}
})
//B类中
public class B{
private static final B instance;
private onClickListener listener;
public static B getInstance(){
if(instance==null){
  instance=new B();
}
return intance;
}

private viod doXXX(){
        if(listener!=null){
            onClick();
        }
    }

public interface onClickListener{
  void onClick();
}
public viod setOnClickListener(onClickListener listener){
   this.listener=listener;
}
}

如果B类无法销毁或者B类无法短时间销毁导致A错过销毁,则销毁A的代码执行后无效果,进而导致内存泄漏

//add监听,放到集合里面
tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
    @Override
    public void onWindowFocusChanged(boolean b) {
        //监听view的加载,view加载出来的时候,计算他的宽高等。
 
        //计算完后,一定要移除这个监听
    tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
    }
});
/***/
SensorManager sensorManager = getSystemService(SENSOR_SERVICE);
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
        sensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST);
        //不需要用的时候记得移除监听
        sensorManager.unregisterListener(listener);
上一篇 下一篇

猜你喜欢

热点阅读