(一
)
查询数据库没有关闭游标
描述:
程序中经常会进行查询数据库的操作,但是经常会有使用完毕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内存泄漏调试经验分享 #### 一、概述 在Android开发中,内存泄漏是一个常见且需要重点关注的问题。由于Android设备通常配置有限,尤其是内存资源较为紧张,因此开发者需要格外注意避免内存泄漏的发生,...
**2.2 Android内存泄漏调试经验分享** 在实践中,开发者可以通过以下几种方法来调试和修复内存泄漏: - **分析堆栈快照**: 使用工具分析堆栈快照,找出哪些对象没有被正确释放。 - **检查生命周期管理**: 确保...
当遇到空指针异常或内存泄漏时,可以使用“内存窗口”查看内存分配和使用情况,或者使用Visual Leak Detector等工具辅助检测内存泄漏。同时,注意分析堆栈信息,通过调用堆栈回溯找到问题源头。 在多线程环境下,...
下面结合我的实际经验,整理下常见定位内存泄漏的方法。 注意:我们的分析前提是Release版本,因为在Debug环境下,通过VLD这个库或者CRT库本身的内存泄漏检测函数能够分析出内存泄漏,相对而言比较简单。而服务器有...
通过这些案例,读者可以学习到如何分析日志、追踪堆栈、使用断点和变量监视,以及如何进行性能剖析和内存泄漏检测。此外,了解如何在设计阶段引入健壮性,例如编写单元测试、使用静态代码分析工具,也是避免问题的...
此外,社区中关于VueJS SSR内存泄漏的讨论和经验分享也非常值得参考,因为它们往往包含了实践中发现的独特问题和有效的解决方案。通过交流和学习,我们可以更好地理解和解决VueJS SSR中的内存泄漏问题,提升应用的...
本篇文章将重点分享一些在使用Visual Studio 2008 (VS2008)进行C++编程时,可能会遇到的不易察觉的错误及其调试方法。 1. **未初始化的变量**:这是一个常见的问题,程序员可能忘记初始化变量,导致程序运行时产生...
pool`命令检查内存池分配情况,以查找内存泄漏。 7. **调试内核模式崩溃**:在内核模式下,WinDbg可以帮助调试蓝屏错误(BSOD)。分析蓝屏转储文件(dump file)可以揭示崩溃时的系统状态。 8. **符号文件和源代码...
书中提供的在线笔记心得问答交流部分,很可能包含了大量的实例分析和读者的经验分享,这对于深化理解和应用调试技术非常有价值。 通过阅读《Windows程序调试》这本书,开发者可以系统地学习和掌握Windows环境下的...
调试技巧方面,张英奎可能会分享一些实战经验,比如如何有效利用日志输出、单元测试和代码审查来辅助调试。日志输出可以在程序运行时记录关键信息,帮助定位问题。单元测试则是通过编写独立的小测试来验证代码功能,...
此外,陈皓可能还会分享一些高级技巧,如使用GDB的Python扩展进行更复杂的调试任务,或者如何结合GDB与其他工具(如Valgrind)一起使用来检测内存泄漏和其他资源管理问题。 另一方面,《GDB调试工具指南》可能是一...
#### 经验分享 - **跟踪技巧**:深入学习跟踪技术,如使用MFC的TRACE宏、ASSERT宏、ASSERT_VALID宏等,有效定位问题。 - **内存管理**:熟练掌握CMemoryState类的使用,有效监测内存使用情况,及时发现并处理内存...
2. **内存泄漏检测**:工具内置了内存泄漏检测功能,能实时监控应用的内存使用情况,及时发现可能导致应用崩溃的内存问题。 3. **CPU与内存性能分析**:提供CPU和内存的实时监控图表,帮助开发者了解应用运行时的...
这对于分析程序行为、定位内存泄漏等问题非常有帮助。 5. **脚本支持**:高级用户可以通过编写脚本来自动化内存操作,实现更复杂的任务,如自动搜索、修改或跟踪内存变化。这大大提高了工作效率,特别是在处理大量...
- **文档记录**:及时记录调试过程中的发现和解决方案,方便后续参考或分享经验。 #### 六、总结 通过本文的介绍,我们可以了解到VxWorks提供的强大调试功能,这些工具和技术不仅能够帮助开发者高效地完成软件调试...
6. **内存泄漏与性能分析**:内存泄漏可能导致程序崩溃或性能下降。学习如何检测和修复内存泄漏,以及如何使用性能分析工具优化代码,是提升程序稳定性和效率的重要部分。 7. **调试Web应用和数据库**:对于Web应用...
### Java开发经验分享:提升代码质量和效率的关键实践 在Java开发领域,良好的编码习惯和实践是确保项目成功、代码质量及团队协作效率的关键。以下是从标题、描述、标签以及部分内容中提炼出的重要知识点,旨在帮助...
- 调试内存错误:如空指针引用、数组越界、内存泄漏等。 - 性能优化:通过分析程序运行时间和内存使用情况,找出瓶颈并进行优化。 - 复杂逻辑分析:在多线程或者并发环境中,dbx可以帮助理解和调试复杂的执行流程...