您的当前位置:首页正文

Android 内存泄漏分析(MemoryAnalyzer)

2024-11-10 来源:个人技术集锦

MemoryAnalyzer的介绍及使用请参见:

Android 内存泄漏分析

编写如下代码(就是一个按钮加一个imageview,不停地点击button,就会翻转90度图片)

Bitmapbt;

@Override

protectedvoidonCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

rotate = (Button) findViewById(R.id.button1);

view = (ImageView) findViewById(R.id.imageView1);

view.setDrawingCacheEnabled(true);

rotate.setOnClickListener(newOnClickListener() {

@Override

publicvoidonClick(Viewarg0) {

// TODO Auto-generated method stub

bt = drawableToBitmap(view.getDrawable());

view.setImageBitmap(rotateBitmap(bt,90));

view.setDrawingCacheEnabled(true);

//bt.recycle();

//bt = null;

}

});

}

效果执行如下:

使用DDMS插件进行进程内存跟踪:

运行一段时间以后,导出当前进程中的内存快照文件。

打开 memery analyzer进行内存文件分析

转换一下,内存dump文件的格式(android 虚拟机与java虚拟机差异)

工具分析的内存疑似泄漏点:

发现疑似第二处为应用的泄漏点:

Android 常见内存泄漏错误

1、集合中对象没清理造成的内存泄露

  我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。

2、资源对象没关闭造成的内存泄露

资源性对象比如(CursorFile文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。因为有些资源性对象,比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null.在我们的程序退出时一定要确保我们的资源性对象已经关闭。

举例(隐形cursorclose释放资源)

Cursor c = getServerIdCursor(serverId);

try {

if (c.moveToFirst()) {

Uri uri = ContentUris.withAppendedId(

RawContacts.CONTENT_URI, c.getLong(0));

uri = Uri.withAppendedPath(uri,

RawContacts.Entity.CONTENT_DIRECTORY);

EntityIterator entityIterator = RawContacts

.newEntityIterator(mContentResolver.query(

uri, null, null, null, null));

if (entityIterator.hasNext()) {

entity = entityIterator.next();

}

entityIterator.close();// 释放cursor防止内存泄漏 fix by

// jhy

userLog("Changing contact ", serverId);

}

} finally {

if (c != null) {

userLog("Changing contact releaseing------ cursor!");

c.close();

c = null;

}

}

3、Bitmap没调用recycle()

  Bitmap对象在不使用时,我们应该先调用recycle()释放内存,然后才它设置为null.

  虽然recycle()从源码上看,调用它应该能立即释放Bitmap的主要内存,但是测试结果显示它并没能立即释放内存。但是我它应该还是能大大的加速Bitmap的主要内存的释放。

4、代码内跨activity对象引用造成的对象还被引用,释放不了。

android SoftReference WeakReference的使用

Soft Reference 虽然和 Weak Reference 很类似,但是用途却不同。被 Soft Reference 指到的对象,即使没有任何 Direct Reference,也不会被清除。一直要到 JVM 内存不足时且没有 Direct Reference 时才会清除,SoftReference 是用来设计 object-cache 之用的。如此一来 SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误(OutOfMemoryError

http://www.cnblogs.com/charley_yang/archive/2010/10/22/1857926.html

显示全文