我已经检查并确保我所有的Cursors
都关闭了。我在严格模式下运行detectLeakedSqlLiteObjects
和detectLeakedClosableObjects
,这从来没有被触发过。但是当在生产环境中运行时,一些用户会崩溃:android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
这种情况会不会是因为数据太大而发生的?
这会不会是因为某个第三方库(比如广告库)让游标处于打开状态?游标是否在所有数据库之间共享?
我还应该检查什么?
1条答案
按热度按时间mtb9vblg1#
这种情况会不会是因为数据太大而发生的?
CursorWindow必须能够容纳至少一行,如果一行大于CursorWindow,则您将收到一条消息/失败,指示CursorWindow的大小和数据的大小(大于前者)。
例如
Window is full: requested allocation 3095146 bytes, free space 2096696 bytes, window size 2097152 bytes
这会不会是因为某个第三方库(比如广告库)让游标处于打开状态?游标是否在所有数据库之间共享?
游标实际上是一个文件,但可以打开/打开的文件(文件句柄)的数量是有限制的。因此,尽管游标不共享。但同时可以打开的文件数量是有限制的。
已经出现的一个问题是,在为每个迭代打开游标的循环之后,游标显然已经关闭了BUT。因此,显然关闭了BUT,但只关闭了最后一个(按照下面链接的 "如何模拟游标窗口分配")。
另一个原因可能是没有足够的内存来获取2048k。
您可能会对以下内容感兴趣:
行太大,无法放入CursorWindow,要求Pos = 0,totalRows = 1;
Android:如何模拟CursorWindowAllocationException崩溃
好的,我可以尝试捕获异常,然后记录数据的大小,这样我至少可以了解正在发生的事情。
是的,如果可能的话,可能是数据库文件的副本(如果使用WAL,可能是文件)。
日志应准确指出故障发生的位置,然后您可以确定问题发生的查询/表,从而能够减少需要调查的代码。您还可以对数据运行测试/提取,例如使用SQLite
length
函数确定长度列。例如基于
SELECT rowid,length(the_column) AS rowsize FROM the_table GROUP BY rowid ORDER BY rowsize DESC;
的东西