(一
)
查询数据库没有关闭游标
描述:
程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor
后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。
示例代码:
Cursor cursor = getContentResolver().query(uri ...);
if (cursor.moveToNext()) {
... ...
}
修正示例代码:
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri ...);
if (cursor != null && cursor.moveToNext()) {
... ...
}
} finally {
if (cursor != null) {
try {
cursor.close();
} catch (Exception e) {
//ignore this
}
}
}
(二
)
构造
Adapter
时,没有使用缓存的
convertView
描述:
以构造ListView
的
BaseAdapter
为例,在
BaseAdapter
中提高了方法:
public View getView(int position, View convertView, ViewGroup parent)
来向ListView
提供每一个
item
所需要的
view
对象。初始时
ListView
会从
BaseAdapter
中根据当前的屏幕布局实例化一定数量的
view
对象,同时
ListView
会将这些
view
对象缓存起来。当向上滚动
ListView
时,原先位于最上面的
list item
的
view
对象会被回收,然后被用来构造新出现的最下面的
list item
。这个构造过程就是由
getView()
方法完成的,
getView()
的第二个形参
View convertView
就是被缓存起来的
list item
的
view
对象
(
初始化时缓存中没有
view
对象则
convertView
是
null)
。
由此可以看出,如果我们不去使用convertView
,而是每次都在
getView()
中重新实例化一个
View
对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。
ListView
回收
list item
的
view
对象的过程可以查看
:
android.widget.AbsListView.java --> void addScrapView(View scrap) 方法。
示例代码:
public View getView(int position, View convertView, ViewGroup parent) {
View view = new Xxx(...);
... ...
return view;
}
修正示例代码:
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView != null) {
view = convertView;
populate(view, getItem(position));
...
} else {
view = new Xxx(...);
...
}
return view;
}
(三
) Bitmap
对象不在使用时调用
recycle()
释放内存
描述:
有时我们会手工的操作Bitmap
对象,如果一个
Bitmap
对象比较占内存,当它不在被使用的时候,可以调用
Bitmap.recycle()
方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:
/**
* Free up the memory associated with this bitmap's pixels, and mark the
* bitmap as "dead", meaning it will throw an exception if getPixels() or
* setPixels() is called, and will draw nothing. This operation cannot be
* reversed, so it should only be called if you are sure there are no
* further uses for the bitmap. This is an advanced call, and normally need
* not be called, since the normal GC process will free up this memory when
* there are no more references to this bitmap.
*/
(四
)
释放对象的引用
描述:
这种情况描述起来比较麻烦,举两个例子进行说明。
示例A
:
假设有如下操作
public class DemoActivity extends Activity {
... ...
private Handler mHandler = ...
private Object obj;
public void operation() {
obj = initObj();
...
[Mark]
mHandler.post(new Runnable() {
public void run() {
useObj(obj);
}
});
}
}
我们有一个成员变量 obj
,在
operation()
中我们希望能够将处理
obj
实例的操作
post
到某个线程的
MessageQueue
中。在以上的代码中,即便是
mHandler
所在的线程使用完了
obj
所引用的对象,但这个对象仍然不会被垃圾回收掉,因为
DemoActivity.obj
还保有这个对象的引用。所以如果在
DemoActivity
中不再使用这个对象了,可以在
[Mark]
的位置释放对象的引用,而代码可以修改为:
... ...
public void operation() {
obj = initObj();
...
final Object o = obj;
obj = null;
mHandler.post(new Runnable() {
public void run() {
useObj(o);
}
}
}
... ...
示例B:
假设我们希望在锁屏界面(LockScreen)
中,监听系统中的电话服务以获取一些信息
(
如信号强度等
)
,则可以在
LockScreen
中定义一个
PhoneStateListener
的对象,同时将它注册到
TelephonyManager
服务中。对于
LockScreen
对象,当需要显示锁屏界面的时候就会创建一个
LockScreen
对象,而当锁屏界面消失的时候
LockScreen
对象就会被释放掉。
但是如果在释放LockScreen
对象的时候忘记取消我们之前注册的
PhoneStateListener
对象,则会导致
LockScreen
无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的
LockScreen
对象没有办法被回收而引起
OutOfMemory,
使得
system_process
进程挂掉。
总之当一个生命周期较短的对象A
,被一个生命周期较长的对象
B
保有其引用的情况下,在
A
的生命周期结束时,要在
B
中清除掉对
A
的引用。
(五
)
其他
Android应用程序中最典型的需要注意释放资源的情况是在
Activity
的生命周期中,在
onPause()
、
onStop()
、
onDestroy()
方法中需要适当的释放资源的情况。由于此情况很基础,在此不详细说明,具体可以查看官方文档对
Activity
生命周期的介绍,以明确何时应该释放哪些资源
_Android_内存泄漏调试.pdf,以下有下载:
相关推荐
二、Android(Java)中常见的容易引起内存泄漏的不良代码 1 (一) 查询数据库没有关闭游标 2 (二) 构造Adapter时,没有使用缓存的 convertView 3 (三) Bitmap对象不在使用时调用recycle()释放内存 4 (四) 释放对象的...
Android内存泄漏调试教程,Android内存泄漏调试教程,Android内存泄漏调试教程
为博客提供的内存泄漏调试的工程,更多的信息要见我的博客
arm环境内存泄漏检测工具valgrind,用于检测arm环境下的内存泄漏
Windows内存泄漏调试工具LeakDiag
在 Linux 平台中调试 C-C++ 内存泄漏方法
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。Valgrind这个名字取自北欧神话中英灵殿的入口。 Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届...
检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏 检测内存泄漏
VC使用CRT调试功能来检测内存泄漏 C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话。在 C/C++ 应用程序...
作为ios开发者,经常会遇到内存泄漏问题,如何才能找到内存泄漏的地方呢,这里介绍几种查看内存泄漏以及调试内存泄漏的方法
word文档 浅谈内存泄漏 内存泄漏的定义 内存泄漏可以分为4类:常发性内存泄漏;偶发性内存泄漏;一次性内存泄漏;隐式内存泄漏
LeakDiag和LDGrapher,windows内存泄漏排查工具,用于进行一些泄漏位置的查找以及可视化展示。
使用 CRT 调试功能来检测内存泄漏.比较好用
理解和探查内存不足内存泄漏 了解Java基本内存管理基本概念 了解发生内存不足/内存泄漏错误的原因和症状 了解如何诊断内存不足/内存泄漏错误 了解如何解决内存不足/内存泄漏错误
几个内存泄漏的例子 new和delete要成对使用 new和delete要匹配 经常看到一些C++方面的书籍中这样提及到内存泄漏问题,这样的说法的意思是比较明白,但对于初学C++程序员还是很难掌握,所以下面举几个反面的...
opencv3和opencv4多线程内存泄漏问题:以cv::resize函数测试结果为例。 使用中可修复或者可避免内存泄漏:1)使用opencv2的版本;2)在代码中设置修复该问题.
Android处理内存泄漏的代码例子。用于演示避免内存泄漏的几种方法,包括:关闭游标、重用适配、回收图像、注销监听、释放引用。
JS内存泄漏检测工具:IEJSLeaksDetector
js内存泄漏检测工具;内存泄漏检测工具IE Javascript leaks detector