首先需要内存分享,这个就先借鉴别人的博客来了。

Eclipse Memory Analysis Tools (MAT) 使用

1.定义:http://inter12.iteye.com/blog/1407492

2.安装及使用:https://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/

3.分析:

               


然后进入主题,开始对某个类出现内存泄露问题进行解决。

public class AView{
Bitmap mBitmap;
XObject mXObjcet;
public AView(){
mBitmap = BitmapFactory.decodeBitmap();//读入内存
mXObject = new XObject(mBitmap);
}
class XObject(){
Bitmap mBitmap;
public XObject(Bitmap _bt){
mBitmap = _bt;
}
}
}

这个时候通过内存分析,多次进入该界面 跳出再进入,会定位到该类的某个bitmap对象占用的内存是没有释放的。


这个时候引入一个java回收的一个概念:

当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。

于是对应这个view的destory方法,增加以下的操作

<pre name="code" class="java">public onDestory(){
	if(mBitmap != null){
		if(!mBitmap.isRecycled()){
			mBitmap.recycle();
		}
                mBitmap = null;
	}
}





继续观察内存情况,我们内存还是没有被释放。而且上面的方法看似正常,其实实际上运行每次执行了一次创建 执行一次销毁都会带来一次内存泄露,即mBitmap.recycle(),并没有成功释放掉这个bitmap内存。

于是继续下面的分析。看到XObject对象持有了这个bitmap的引用,导致了这个情况,调用了recycle方法但是每次没有被成功释放。

总结 保证我们调用bitmap的recycle方法之前,需要确认没有任何对象引用了bitmap对象这块内存,这样的话才能完成bitmap的释放,这里就是这个XObject的对象中有个局部变量持有了这个bitmap对象的引用,导致释放的时候无法完成释放。


对应解决办法:

方案1:


public onDestory(){
	if(mBitmap != null){
                mXObject = null;
		if(!mBitmap.isRecycled()){
			mBitmap.recycle();
		}
                mBitmap = null;
	}
}

最简单的一种解决的方法,因为mCanvas置为null以后,就没有引用指向mCanvas对象,所以mCanvas对象内部的mBitmap对象的引用也就无效了,此时mCanvas就对mBitmap.recycle()没有影响。这个也是目前我们CC里面最常用采用的方法。前提:mCanvas是它所指向的Canvas对象的唯一的引用,如果Canvas对象还有其他的引用,则必须将其他的引用也都置为null,最后导致没有引用指向mCanvas对象,此方法才能生效。

方案2:

把mCanvas由类成员变量改为类方法的局部变量。 方法调用结束mCanvas对象自然会被释放掉。
这种方法需要规范好类定义,还有代码习惯,尽量少定义成员变量引用其他对象,这样的话也能够更好使用方法1来解决问题。