安卓系统:如何模拟CursorWindowAllocationException崩溃



我想模拟android.database.CursorWindowAllocationException崩溃。我正在开发一个巨大的代码库,每个屏幕上都有很多房间数据库查询。我不确定这个崩溃发生在哪个数据库查询中,也不确定这个故障发生在哪个场景中。那么,有什么办法让simulate崩溃吗?我试着在for循环中保持10 database cursors几乎打开,但无法再现崩溃。我已附上crashlytics日志以供参考。

Fatal Exception: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. 
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:309)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:141)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:269)
at androidx.room.InvalidationTracker$1.checkUpdatedTable(InvalidationTracker.java:461)
at androidx.room.InvalidationTracker$1.run(InvalidationTracker.java:431)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)

以下模拟了这样的崩溃(但将其捕获(:-

var lastIndex = 0
try
{
for (i in 0..1999) {
lastIndex = i
val csr: Cursor = db.openHelper.writableDatabase.query(SimpleSQLiteQuery("SELECT * FROM model"))
val count = csr.count.toLong()
}
}catch (  e:java.lang.Exception)
{
Log.d(
"DBEXCEPTION",
"Exception trapped at INDEX " + lastIndex + " Message was " + e.message
)
e.printStackTrace()
}
}
  • 其中db@Database注释类的实例(等等(
  • 0..1999作为2000打开的游标应该足够总是失败
    • 注意,空的游标看起来并不会导致失败,并且不以某种方式实际遍历游标也不会导致失败。因此csr.count.toLong
    • 我怀疑Cursor下面的文件是由SQLite正确创建/打开和关闭的,直到尝试访问Cursor,文件才真正打开,然后一直打开,直到文件关闭

然后日志将包含以下内容:-

2022-09-20 09:48:01.929 E/CursorWindow: CursorWindow: mmap() failed: errno=12.
2022-09-20 09:48:01.930 D/DBEXCEPTION: Exception trapped at INDEX 1415 Message was Could not allocate CursorWindow '/data/user/0/a.a.so73757679kotlinroomuniqueconflict/databases/the_database.db' of size 2097152 due to error -12.
2022-09-20 09:48:01.930 W/System.err: android.database.CursorWindowAllocationException: Could not allocate CursorWindow '/data/user/0/a.a.so73757679kotlinroomuniqueconflict/databases/the_database.db' of size 2097152 due to error -12.
2022-09-20 09:48:01.930 W/System.err:     at android.database.CursorWindow.nativeCreate(Native Method)
2022-09-20 09:48:01.930 W/System.err:     at android.database.CursorWindow.<init>(CursorWindow.java:139)
2022-09-20 09:48:01.930 W/System.err:     at android.database.CursorWindow.<init>(CursorWindow.java:120)
2022-09-20 09:48:01.930 W/System.err:     at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:202)
2022-09-20 09:48:01.931 W/System.err:     at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
2022-09-20 09:48:01.931 W/System.err:     at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:140)
2022-09-20 09:48:01.931 W/System.err:     at android.app.Activity.performCreate(Activity.java:7994)
2022-09-20 09:48:01.931 W/System.err:     at android.app.Activity.performCreate(Activity.java:7978)
2022-09-20 09:48:01.931 W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
2022-09-20 09:48:01.931 W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
2022-09-20 09:48:01.931 W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
2022-09-20 09:48:01.931 W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
2022-09-20 09:48:01.931 W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
2022-09-20 09:48:01.931 W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
2022-09-20 09:48:01.931 W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
2022-09-20 09:48:01.932 W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2022-09-20 09:48:01.932 W/System.err:     at android.os.Looper.loop(Looper.java:223)
2022-09-20 09:48:01.932 W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7656)
2022-09-20 09:48:01.932 W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2022-09-20 09:48:01.932 W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
2022-09-20 09:48:01.932 W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-09-20 09:48:02.003 W/libc: malloc(4194304) failed: returning null pointer
2022-09-20 09:48:02.003 A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x80000 in tid 23176 (RenderThread), pid 23153 (muniqueconflict)

需要注意的是,当前的问题并不完全是游标的数量,而是游标的底层是一个文件,而且(我认为(问题是数据库本身将有3个未关闭文件分配的数量(对于数据库,-wal文件和-shm文件(。

然而,也可能存在与内存相关的问题,因为此测试会导致malloc错误(无法获得4Mb(。

最新更新