CursorWindowAllocationException が発生した時の対処方法です。

0. 環境

[Windows] 7

[Java] 1.8

[Android] 5.1.1

[Android API] 26

1. 問題

  • 開発中のAndroidアプリでSQLiteを使ってます。

    サブクエリを使って、今までより抽出データが多くなるSQLを書いたところ、画面遷移中に頻繁にクラッシュするようになりました。

    しかも、特定のテスト機(Galaxy S4(Android5.0.1))のみです。

    • (A)エラー内容

      Fatal Exception: android.database.CursorWindowAllocationException
      Cursor window allocation of 2048 kb failed. # Open Cursors=700 (# cursors opened by this proc=700)
      
    • (B)エラー箇所

      • 前述のサブクエリを適用した箇所とは全く別の箇所が毎回落ちるポイントでした。(下記2行目)

        Cursor cursorCountUsers = db.rawQuery("SELECT COUNT(user_id) FROM users", null);
        cursorCountUsers.moveToFirst();
        int countUserId = cursorCountUsers.getInt(0);
        return countUserId;
        

2. 対策

  • Slackoverflowで同じ問題を見つけました。

    まず、毎回同じ箇所で落ちるので、上記(B)にcursorCountUsers.close();を入れたけど直りませんでした。

    次に、ソースコード全体を”Cursor”で検索をかけ、closeしてない箇所が20くらいあったので全てに追記したところ問題は解消されました。

  • Javaはgcがあると思ってcloseを甘く見てましたね・・・気を付けないと。

    RAMの空きが30数%あるのに落ちるということは、Slackoverflowの回答者が言う通り、cursorのために用意されたメモリ容量に上限があって、今までよりメモリを使うSQLを書いたせいで、そこが圧迫されたということかもしれません。