Android进行数据库操作时,可能会遇到如下异常:

E AndroidRuntime: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14)E AndroidRuntime: at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)E AndroidRuntime: at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:553)E AndroidRuntime: at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:323)E AndroidRuntime: at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:298)E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:505)E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:416)

由于SQLite底层的代码并不是很好分析,一直以来这个问题的具体原因很难定位。
从我目前接触到的信息来看,关于这个问题的原因,江湖传言有这么三个:
1、内存耗尽(几乎是最显而易见的原因);
2、进程的文件句柄Fd耗尽;
3、SQLite的临时文件不可用(自己没证实过)。


对于内存耗尽的原因比较好定位。
当大家怀疑是内存问题导致SQLite异常时,只需要在crash等日志中搜索memory关键即可:

W art : Throwing OutOfMemoryError "Could not allocate JNI Env"

如果是内存原因,那么应该可以看到类似上述的日志。
这个时候就要考虑系统当时是真的运行了过多的进程,还是存在内存泄露的问题。


对于文件句柄耗尽的原因,可以搜索类似如下的log:

E art : ashmem_create_region failed for 'indirect ref table': Too many open files

SQLite最终会调用ashmem_create_region()来分配共享内存。
如果出现上述log,那么应该就是开启了过多的文件,导致Fd耗尽。
比较常见的原因就是:Cursor开启后没有关闭。

此外,还有一些其它的场景,例如:
进程一直存在,然后不断地新建并运行HandlerThread。
如果HandlerThread在功能执行结束后不主动quit的话,
进程中就会积累出越来越多的HandlerThread。
由于HandlerThread对应的Looper也会持有Fd,
最终也会导致Fd耗尽,出现前文提到的异常。

如果怀疑是这种问题,可以使用root的手机测试你的APK。
利用ps或ps -A得到APK进程对应的pid,然后执行下述命令:

ls -al /proc/pid/fd

执行结果类似于:
Android SQLite数据库异常: unable to open database file_第1张图片
图中的数字就是fd编号。

如果随着APK运行(测试),Fd不断变大(正常情况下,释放后会复用),那么就可以确定Fd存在泄露。


对于第三种情况,没仔细研究过,看过很多人写,内容几乎一样。
附上链接以备万一:http://www.jianshu.com/p/6ad0491404da

更多相关文章

  1. Android 获得当前进程PackageName
  2. android Handler内存泄露 kotlin内存泄露处理
  3. 【转】 关于Android堆内存的设置
  4. Android中的获取内存信息的相关命令
  5. Android handler的Context内存泄露
  6. 穿针引线,帮你回忆, 汇总:Android系统启动流程 & 应用程序'进程'启

随机推荐

  1. Android(安卓)仿支付宝密码输入页面
  2. Android(安卓)面试:常见问题总结
  3. Android解析XML之XmlPullParser
  4. Android监听HOME键的最简单的方法
  5. android 水平进度对话框
  6. Android之NetworkOnMainThreadException
  7. android 关于gallery 的平滑代码滚动
  8. android WebView结合javascript相互调用
  9. 文件读写
  10. Android(安卓)跳转Activity并通过Bundle