Android 查询数据库时 项目出现 OOM (不断引发GC)

本文介绍了一次由于查询数据库时出现死循环而导致应用程序频繁触发GC并最终OOM的经历。通过详细分析logcat日志及代码,定位到了问题根源,并给出了修复方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天项目遇到一个棘手的问题:在查询数据库数据记录(全部显示在屏幕上)时,不断引发gc操作,最后 oom

logcat日志如下:

02-15 10:53:25.853: I/System.out(2223): DDP: come here add one recode
02-15 10:53:30.843: I/System.out(2223): DDP: cursor.count = 3
02-15 10:53:31.273: D/dalvikvm(2223): GC freed 934 objects / 77736 bytes in 83ms
02-15 10:53:31.873: D/dalvikvm(2223): GC freed 107 objects / 29960 bytes in 88ms
02-15 10:53:32.593: D/dalvikvm(2223): GC freed 123 objects / 24176 bytes in 102ms
02-15 10:53:33.553: D/dalvikvm(2223): GC freed 44 objects / 29368 bytes in 115ms
02-15 10:53:34.813: D/dalvikvm(2223): GC freed 3 objects / 41632 bytes in 153ms
02-15 10:53:36.563: D/dalvikvm(2223): GC freed 3 objects / 62408 bytes in 218ms
02-15 10:53:38.283: D/dalvikvm(2223): GC freed 3 objects / 93576 bytes in 265ms
02-15 10:53:40.103: D/dalvikvm(2223): GC freed 2 objects / 48 bytes in 322ms
02-15 10:53:41.853: D/dalvikvm(2223): GC freed 3 objects / 140328 bytes in 325ms
02-15 10:53:43.804: D/dalvikvm(2223): GC freed 2 objects / 48 bytes in 387ms
02-15 10:53:45.932: D/dalvikvm(2223): GC freed 2 objects / 48 bytes in 556ms
02-15 10:53:47.762: I/dalvikvm-heap(2223): Clamp target GC heap from 24.386MB to 24.000MB
02-15 10:53:47.762: D/dalvikvm(2223): GC freed 3 objects / 210456 bytes in 528ms
02-15 10:53:49.462: I/dalvikvm-heap(2223): Clamp target GC heap from 26.025MB to 24.000MB
02-15 10:53:49.462: D/dalvikvm(2223): GC freed 2 objects / 48 bytes in 475ms
02-15 10:53:49.462: I/dalvikvm-heap(2223): Clamp target GC heap from 24.025MB to 24.000MB
02-15 10:53:49.472: I/dalvikvm-heap(2223): Grow heap (frag case) to 24.000MB for 26-byte allocation
02-15 10:53:50.013: I/dalvikvm-heap(2223): Clamp target GC heap from 26.025MB to 24.000MB
02-15 10:53:50.023: D/dalvikvm(2223): GC freed 0 objects / 0 bytes in 550ms
02-15 10:53:50.023: I/dalvikvm-heap(2223): Forcing collection of SoftReferences for 24-byte allocation
02-15 10:53:50.522: I/dalvikvm-heap(2223): Clamp target GC heap from 26.025MB to 24.000MB
02-15 10:53:50.522: D/dalvikvm(2223): GC freed 0 objects / 0 bytes in 500ms
02-15 10:53:50.522: E/dalvikvm-heap(2223): Out of memory on a 24-byte allocation.




找了半天,原来以为是项目中的一些大图片导致的内存吃紧。一直没有找到问题的症结所在。

今天自己写了一个操作数据库的demo,发现原来是查询代码出了问题。

原代码如下:

public List<Map<String,Object>> queryAllJournal(){
List<Map<String,Object>> journalData = new ArrayList<Map<String,Object>>();
if(db != null){
Cursor cursor = db.query(JournalTB.JOURNAL_TABLE, null, null, null, null, null, null);
if (cursor.getCount() > 0){
System.out.println("DDP: cursor.count = " + cursor.getCount());
cursor.moveToFirst();
HashMap item = null;
while(!cursor.isAfterLast()){ //仔细看看,这是一个死循环啊,cursor位置没有改变啊!!!
item = new HashMap<String,Object>();
item.put("id", cursor.getInt(JournalTB.ID_COL_INDEX));
item.put("date", cursor.getString(JournalTB.DATE_COL_INDEX));
item.put("description", cursor.getString(JournalTB.DESCRIPTION_COL_INDEX));
journalData.add(item);
}

}
cursor.close();
}

return journalData;
}


怎么解决呢?

仔细看了好久,唉,真是该死啊!有一个死循环在代码中。

忘记了下面这一句!,唉,悲剧啊

cursor.moveToNext();


### Android 数据库操作中的内存管理与 GC 优化 在 Android 开发中,数据库操作可能导致内存不足以及频繁触发垃圾回收(Garbage Collection, GC)。为了缓解这一问题,可以采取多种策略来优化资源管理和性能。 #### 使用懒加载减少初始开销 通过实现懒加载机制,在对象实际需要才初始化它们。这种方法不仅减少了应用程序启动的内存消耗,还允许开发者在未来轻松扩展 `onLowMemory()` 方法而无需大幅修改现有代码结构[^1]。 #### 合理释放不再使用的资源 当某些布局或数据库对象不可见或者不被使用,应该及将其销毁以腾出更多可用空间给其他更重要的组件。如果未能充分清理这些无用的数据,则可能会迫使操作系统更加积极地终止进程——这其中包括可能正在运行的应用本身。因此,建议应用尽其所能去释放那些能够重新创建但成本较低的对象,从而提高整个设备上的用户体验,同也间接提升了自己程序再次快速恢复的能力[^1]。 #### 避免实系统常见的误区 值得注意的是,标准虚拟机通常不会针对实性能做特别优化;相反,大多数非实系统的重点在于最大化整体吞吐量而非逐毫秒满足截止间的要求。这意味着即使偶尔延迟也不会显著影响最终效果,只要总体效率高即可接受。所以对于像Android这样的环境来说,关注点应放在如何有效利用有限硬件条件下的计算能力之上而不是单纯追求瞬间响应速度[^2]。 以下是关于如何改善因数据库交互引发OOM 和过度依赖GC状况的一些具体措施: ```java // 示例:关闭Cursor以防止泄漏 public void closeCursorsIfNotClosed(Cursor cursor){ if(cursor != null && !cursor.isClosed()){ cursor.close(); } } ``` 另外还需注意以下几点: - **确保游标的正确关闭**:每次查询完成后都需确认相应的 Cursor 已经妥善处理完毕。 - **批量更新代替单条记录逐一写入**:这样既能加快执行速度又能降低中间状态保存带来的额外负担。 - **限制返回的结果数量**:特别是在分页显示场景下,仅获取当前页面所需部分就足够了。 最后提醒一点就是保持良好的编程习惯非常重要,比如尽早发现潜在风险并通过单元测试验证改动后的稳定性等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值