内存泄漏、资源泄漏、空指针等问题的分析与总结

一、内存泄漏ACTIVITY_LEAK

1、静态变量持有Activity对象,导致Activity无法释放   

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
      
      
public class MainActivity extends Activity {
private static Context mContext ;
private static View mView ;
@override
protected void onCreated ( Bundle savedInstatenceState ){
super . onCreated ( savedInstanceState );
setContentView ( R . layout . activity_main );
mContext = this ; //..........1
mView = new View ( this ); //..........2
}

}
因为静态变量的生命周期与JVM相同(与application相同),导致Context生命周期(activity的生命周期)与与JVM相同(与application相同)


解决方法:杜绝静态变量持有activity


 2、单例模式持有Activity对象,导致Activity无法释放

         
    public class  GameNotFreeFlowDialogActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FreeFlowUtil.getInstance().showMessageDialog(GameNotFreeFlowDialogActivity.this, FreeFlowUtil.FLAG_DOWNLOAD_MESSAGE, new FreeFlowDialog.FreeFlowClickListener() {
            @Override
            public void doClickEvent() {
                final DownloadInfo info = getIntent()
                        .getParcelableExtra("downloadinfo");
                AppClickActionUtils.launchGameCenterDialogActivity(getApplicationContext(), info);
                finish();
            }

            @Override
            public void cancelClickEvent() {
                finish();
            }

        });
    }

}

在GameNotFreeFlowDialogActivity.onCreate方法中调用了单例类FreeFlowUtil的showMessageDialog()方法,

其中FreeFlowUtil的showMessageDialog()方法中第一个参数需要传入Context类。 

由于FreeFlowUtil类为单例模式,生命周期与JVM相同(与application相同),在FreeFlowUtil类创建了mChinaUnicomAlertDialog对象并传入了GameNotFreeFlowDialogActivity的Context,导致Context生命周期(GameNotFreeFlowDialogActivity的生命周期)同FreeFlowUtil相同,导致了泄漏问题。

解决方法:

方法一:不用单例模式   

方法二:将Activity的Context改为Application的Context:getApplicationContext(),这样单例模式持有的就不是单个activity了

注意:不是所有的Activity的Context都可以替换为getApplicationContext(),getApplicationContext()在startActivity时要新建task,而且在任何时候都不能创建dialog


 3、属性无限循环动画持有了Activity里的View,View持有Activity对象,导致Activity无法释放

属性动画中的无限循环动画,在activity的onDestroy中没有停止,导致动画持有了activity的view,view又持有了activity

解决方法:在activity的onDestroy中停止动画


4、  handler导致的内存泄漏(非静态内部类持有外部类的引用导致的内存泄漏)

当handler内部类在不停的处理消息,或者handler内部类在消息发送很长一段时间才处理,会导致内存泄漏。

由于handler是非静态内部类他是一定会持有外部类的引用的,它又在不停的处理消息(或者当activity不可见是它仍在处理消息),所以它一直持有activity对象,导致Activity无法释放


在 Java 语言中,非静态内部类、匿名内部类将持有一个对外部类的隐式引用,而静态内部类则不会持有一个对外部类的隐式引用

解决方法:

方法一:所以要将handler内部类改为静态内部类;如果需要传入外部类的对象,那么hanler初始化时传入外部类的对象要是弱引用;将所有引用的外部类成员使用WeakReference对象

方法二:在activity的onDestroy的时候手动清除Message

@Override
    protected void onDestroy() {
        super.onDestroy();
 
        mHandler.removeCallbacksAndMessages(null);  // 需要在Activity生命周期结束时清除掉CallbacksAndMessages
    }

5、小结

禁止任何生命周期与activity生命周期不一致的结构持有activity,结构包括(静态变量、单例模式、动画、生命周期不一致的非静态内部类、匿名类)。有人说了那静态内部类不也和activity生命周期不一致吗,因为是静态不要紧啊只要不持有activity就没事啊,静态内部类则不会持有一个对外部类的隐式引用。所以只要不持有就没事。

6、其他解决内存泄漏优化内存的方法


(1)java中的基本方法

*使用字符串与包装类时,尽量用直接量创建

*使用StringBuilder和StringBuffer进行字符串连接(而不用String,因为会造成多个对象)

*尽早释放无用的对象引用(及时赋为null)

*尽量少用静态变量

*避免在循环中创建java对象

*缓存经常使用的对象(使用hashmap缓存)

*考虑弱引用、软引用

(2)android中的方法

* 布局尽量减少层级

*布局尽量减少颜色重绘

*默认图片以加载的形式加载,不放在布局background中

*缩小图片大小,能用.9图的用.9图


二、资源泄漏(RESOURCE_LEAK

及时对资源进行关闭,对于Try catch语句,需要在Finally分支下保证关闭。

public static String getFileMD5(File file) {
		if (!file.isFile()) {
			return null;
		}
		MessageDigest digest = null;
		FileInputStream in = null;
		byte buffer[] = new byte[1024];
		int len;
		try {
			digest = MessageDigest.getInstance("MD5");
			in = new FileInputStream(file);
			while ((len = in.read(buffer, 0, 1024)) != -1) {
				digest.update(buffer, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}finally {
			CommonUtils.closeQuietly(in);  //及时关闭
		}
		return bytesToHexString(digest.digest());
	}
  /**
	 * 静默关闭申请资源,防止产生 RESOURCE_LEAK
	 * @param closeable
	 */
	public static void closeQuietly(Closeable closeable) {
		if (closeable != null) {
			try {
				closeable.close();
			} catch (Exception ex) {
				// TODO: 2016/1/15 Log or ignore
			}
		}
	}
三、空指针( NULL_DEREFERENCE

一般未对引用判空鉴定。判空即可


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值