2048K SQLite Android Database Cursor database failed

I have a routine that runs different queries on an SQLite database many times per second. After a while I get an error

"android.database.CursorWindowAllocationException: - Cursor window allocation of 2048 kb failed. # Open Cursors = " displayed in LogCat.

I had an application log memory usage, and indeed, when usage reaches a certain limit, I get this error, meaning that it ends. My intuition tells me that the database engine creates a new buffer (CursorWindow) every time I run the query, and although I mark .close () cursors, neither the garbage collector nor SQLiteDatabase.releaseMemory() frees up the memory fast enough, I think that the solution may be to “force” the database to always write to the same buffer, rather than creating new ones, but I could not find a way to do this. I tried to create an instance of my own CursorWindow and tried to configure it, and SQLiteCursor failed.

¿Any ideas?

EDIT: repeat the sample code request from @GrahamBorland:

 public static CursorWindow cursorWindow = new CursorWindow("cursorWindow"); public static SQLiteCursor sqlCursor; public static void getItemsVisibleArea(GeoPoint mapCenter, int latSpan, int lonSpan) { query = "SELECT * FROM Items"; //would be more complex in real code sqlCursor = (SQLiteCursor)db.rawQuery(query, null); sqlCursor.setWindow(cursorWindow); } 

Ideally, I would like to be able to .setWindow() before giving a new request, and every time I get new data, the data is placed in the same CursorWindow .

+65
android memory sqlite memory-leaks cursor
Jul 05 2018-12-12T00:
source share
8 answers

The most common cause of this error is not closed cursors. Make sure you close all cursors after using them (even in case of an error).

 Cursor cursor = null; try { cursor = db.query(... // do some work with the cursor here. } finally { // this gets called even if there is an exception somewhere above if(cursor != null) cursor.close(); } 
+100
Mar 20 '13 at 22:43
source share
— -

If you need to dig a significant amount of SQL code, you can speed up debugging by placing the following code snippet in your MainActivity to enable StrictMode. If missing database objects are detected, your application will now crash with log information, indicating exactly where your leak is. It helped me find a scam in minutes.

 @Override protected void onCreate(Bundle savedInstanceState) { if (BuildConfig.DEBUG) { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build()); } super.onCreate(savedInstanceState); ... ... 
+79
Jan 26 '15 at 17:42
source share

I just experienced this problem - and the proposed answer not to close the cursor while valid was not the way I fixed it. My problem was closing the database when SQLite tried to move the cursor. I would open the database, query the database to get a pointer to the data set, close the database and iterate over the cursor. I noticed that whenever I click on a specific entry in this cursor, my application crashes with the same error in the OP.

I assume that in order for the cursor to access certain records, it needs to re-query the database, and if it is closed, it will cause this error. I fixed it without closing the database until I did all the work I needed.

+11
Aug 14 '13 at 10:12
source share

Indeed, Android SQLite cursor windows have a maximum size of 2 MB, and anything larger than this will result in the indicated error. This error is mainly caused by either a large byte array of images stored as blobs in the SQL database, or too long strings. Here is how I fixed it.

Create a Java class, for example. FixCursorWindow and put below code in it.

  public static void fix() { try { Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize"); field.setAccessible(true); field.set(null, 102400 * 1024); //the 102400 is the new size added } catch (Exception e) { e.printStackTrace(); } } 

Now go to your application class (create one if you don't already have one) and make a call to FixCursorWindow as follows

public class application extends the application {

 public void onCreate() { super.onCreate(); CursorWindowFixer.fix(); } 

}

Finally, make sure you include your application class in your manifest in the application tag, like this

  android:name=".App"> 

That's all, now it should work great.

+3
Jun 06 '18 at 17:11
source share

If you are using Android P, you can create your own cursor window, for example:

 if(cursor instanceof SQLiteCursor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { ((SQLiteCursor) cursor).setWindow(new CursorWindow(null, 1024*1024*10)); } 

This allows you to resize the cursor window for a particular cursor without resorting to reflections.

0
Jul 04 '19 at 11:32
source share

This is a normal exception, especially when we use external SQLite. You can solve this by closing the Cursor object as shown below:

 if(myCursor != null) myCursor.close(); 

This means that if the cursor has memory and it is open, then close it so that the application runs faster, all methods will take up less space, and the functions associated with the database will also be improved.

-one
Sep 18 '18 at 7:06
source share

The main reason for this error is not closing the cursor that opens. Therefore, if you open the cursor anywhere in the program, do not forget to close it.

For example, cursor c = null; ............................. cursor.close () https://ranjithandroid.blogspot.com/

-one
Apr 29 '19 at 7:57
source share
 public class CursorWindowFixer { public static void fix() { try { Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize"); field.setAccessible(true); field.set(null, 102400 * 1024); } catch (Exception e) { e.printStackTrace(); } } } 
-3
Mar 09 '18 at 2:00
source share



All Articles