Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What could be causing this SQLite CursorWindowAllocationException?

My Google Play dev console has reported its first crash to me for my Android app. It looks like SQLite was unable to allocate memory to the cursor, but I've never seen this before and can't reproduce it. Any ideas?

Stackgrace reported by Google:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.NsouthProductions.gradetrackerpro/com.NsouthProductions.gradetrackerpro.Activity_Category}: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=530 (# cursors opened by this proc=530)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access$900(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=530 (# cursors opened by this proc=530)
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.CursorWindow.<init>(CursorWindow.java:100)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:301)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
at com.NsouthProductions.gradetrackerpro.DBAdapter.getCourse(DBAdapter.java:401)
at com.NsouthProductions.gradetrackerpro.Activity_Category$CategoryActivityFragment.setListData(Activity_Category.java:196)
at com.NsouthProductions.gradetrackerpro.Activity_Category$CategoryActivityFragment.onCreateView(Activity_Category.java:182)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:570)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1189)
at android.app.Activity.performStart(Activity.java:5436)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
... 11 more

Where it failed in my DBAdapter class.

public Course getCourse (int rowId) throws SQLException {
        Cursor c =
                db.query(true, TABLE_COURSES, new String[] {KEY_ID, KEY_TITLE,
                KEY_YEAR, KEY_SEASON, KEY_CREDIT}, KEY_ID + "=" + rowId, null, null, null, null, null);
        if (c != null) {
            c.moveToFirst();
        }
        Course course = new Course(c.getInt(0), c.getString(1), c.getInt(2), c.getString(3), c.getDouble(4));
        return course;
    }

Where the DBAdapter function is called. At this point in the activity, the db has already been opened, queried, and closed successfully.

public void setListData(){
            db.open();
            Grade[] g = db.getGradesInCategory(catId);
            this.getActivity().setTitle(db.getCourse(courseId).getTitle());
            db.close();
like image 535
NSouth Avatar asked Dec 26 '22 03:12

NSouth


2 Answers

That is an OutOfMemoryError, in effect. Quoting the comments for that exception class:

This exception is thrown when a CursorWindow couldn't be allocated, most probably due to memory not being available.

The error message shows that you have 530 open Cursor objects, which may be part of your problem. For example, you are leaking a Cursor in your getCourse() method. Make sure that you close your Cursor as soon as you are done with it.

If that does not help, you will need to treat this like an OutOfMemoryError and determine where else you are wasting heap space, perhaps by using tools like MAT.

like image 106
CommonsWare Avatar answered Dec 28 '22 08:12

CommonsWare


Cursors need to be closed:

Cursor c = db.query(...);
try {
    ...
} finally {
    c.close();
}
like image 24
CL. Avatar answered Dec 28 '22 07:12

CL.