Cursor.moveToNext偶尔会抛出无法解释的异常

时间:2014-06-20 13:49:19

标签: android sqlite android-sqlite sqlcipher dexguard

我们在混淆(Dexguard)Android应用程序中的Android 4.4.2(Nexus 7平板电脑)上使用SQLite(实际上是SQLCipher)。我们有ContentProviders来访问SQLite / SQLCipher数据库。其中一个ContentProviders从队列表返回消息。定期处理此队列 - 我们从队列中检索消息,然后使用cursor.moveToNext()迭代它们:

// Get cursor to iterate unsent messages
Cursor cursor = queueHelper.getMessages(Queue.STATUS_NEW);

try {
    // Check if there are any unsent messages
    if (cursor == null || cursor.getCount() == 0) {
        // No queued messages to send
        return;
    }

    // Send messages
    while (cursor.moveToNext()) {

        // Do stuff
    }
}

这在我们自己的开发和测试期间可靠地工作,但是在现场我们看到偶然但重复的问题,在成功处理排队的消息之后,上面的cursor.moveToNext()调用抛出了IllegalStateException(注意) ,总是排0 col 0):

java.lang.IllegalStateException: get field slot from row 0 col 0 failed
    at net.sqlcipher.CursorWindow.getLong_native(Native Method)
    at net.sqlcipher.CursorWindow.getLong(:446)
    at net.sqlcipher.AbstractWindowedCursor.getLong(:110)
    at net.sqlcipher.AbstractCursor.moveToPosition(:199)
    at net.sqlcipher.AbstractCursor.moveToNext(:228)
    at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
    at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)

在其他情况下,此行反而抛出CursorIndexOutOfBoundsException(请注意每次报告的实际索引/大小更改):

net.sqlcipher.CursorIndexOutOfBoundsException: Index 98 requested, with a size of 98
    at net.sqlcipher.AbstractCursor.?(:556)
    at net.sqlcipher.AbstractWindowedCursor.?(:222)
    at net.sqlcipher.AbstractWindowedCursor.getLong(:101)
    at net.sqlcipher.AbstractCursor.moveToPosition(:199)
    at net.sqlcipher.AbstractCursor.moveToNext(:228)
    at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
    at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)

我们还没有能够重现任何一个问题,只有日志文件才能继续。这些日志表明成功处理行后出现问题。在此异常之后,该过程重新启动并继续进行而不会出现问题。我们无法理解为什么moveToNext会抛出异常 - 例如如果它在1-10行上工作,为什么要移到第11行会抛出异常? Cursor.moveToNext的文档说:

Move the cursor to the next row. 

This method will return false if the cursor is already past the last entry in the result set.

因此它应该成功移动到next(并返回true)或失败(并返回false),而不是抛出这些奇怪的异常。

这听起来像是我们代码中的一个问题,还是一个SQLite问题,一个SQLCipher问题,或者与我们的混淆过程有关,或者是Dexguard,还是我们如何使用它?有什么建议吗?

0 个答案:

没有答案