但是一旦 Cursor 泄漏累计到一定数目(通常为数百个)必然会出现无法查询数据库的情况,只有等数据库服务所在进程死掉重启才能恢复正常。通常的出错信息如下,指出某 pid 的程序打开了 866 个 Cursor 没有关闭,导致了 exception: 复制代码 代码如下: 3634 3644 E JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.) 3634 3644 E JavaBinder: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=866 (# cursors opened by pid 1565=866) 3634 3644 E JavaBinder: at android.database.CursorWindow.(CursorWindow.java:104) 3634 3644 E JavaBinder: at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198) 3634 3644 E JavaBinder: at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147) 3634 3644 E JavaBinder: at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:141) 3634 3644 E JavaBinder: at android.database.CursorToBulkCursorAdaptor.getBulkCursorDescriptor(CursorToBulkCursorAdaptor.java:143) 3634 3644 E JavaBinder: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:118) 3634 3644 E JavaBinder: at android.os.Binder.execTransact(Binder.java:367) 3634 3644 E JavaBinder: at dalvik.system.NativeStart.run(Native Method)
1. Cursor 检测原理 在 Cursor 对象被 JVM 回收运行到 finalize() 方法的时候,检测 close() 方法有没有被调用,此办法在 ContentResolver 里面也得到应用。简化后的示例代码如下: 复制代码 代码如下: import android.database.Cursor; import android.database.CursorWrapper; import android.util.Log; public class TestCursor extends CursorWrapper { private static final String TAG = "TestCursor"; private boolean mIsClosed = false; private Throwable mTrace; public TestCursor(Cursor c) { super(c); mTrace = new Throwable("Explicit termination method "close()" not called"); } @Override public void close() { mIsClosed = true; } @Override public void finalize() throws Throwable { try { if (mIsClosed != true) { Log.e(TAG, "Cursor leaks", mTrace); } } finally { super.finalize(); } } }