[英]android content provider robustness on provider crash
在android平台(在ICS上已确认)上,如果内容提供者在客户端处于查询中间(即具有打开的游标)时死亡,则框架决定杀死持有打开的游标的客户端进程。
这是我使用下载管理器查询尝试执行此操作后休眠的logcat输出。 “睡眠”是为了重现问题。 您可以想象,当提供者在正确/错误的时间死亡时,它会在常规用例中发生。 然后杀死com.android.media(托管downloadProvider)。
“杀死com.example(pid 12234),因为提供程序com.android.providers.downloads.DownloadProvider即将死于android.process.media”
我在ActivityManagerService :: removeDyingProviderLocked中跟踪了此代码
10203 private final void removeDyingProviderLocked(ProcessRecord proc,
10204 ContentProviderRecord cpr) {
10205 synchronized (cpr) {
10206 cpr.launchingApp = null;
10207 cpr.notifyAll();
10208 }
10210 mProvidersByClass.remove(cpr.name);
10211 String names[] = cpr.info.authority.split(";");
10212 for (int j = 0; j < names.length; j++) {
10213 mProvidersByName.remove(names[j]);
10214 }
10215
10216 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10217 while (cit.hasNext()) {
10218 ProcessRecord capp = cit.next();
10219 if (!capp.persistent && capp.thread != null
10220 && capp.pid != 0
10221 && capp.pid != MY_PID) {
10222 Slog.i(TAG, "Kill " + capp.processName
10223 + " (pid " + capp.pid + "): provider " + cpr.info.name
10224 + " in dying process " + (proc != null ? proc.processName : "??"));
10225 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10226 capp.processName, capp.setAdj, "dying provider "
10227 + cpr.name.toShortString());
10228 Process.killProcessQuiet(capp.pid);
10229 }
10230 }
10231
10232 mLaunchingProviders.remove(cpr);
10233 }
这是策略决定,还是提供者死亡后游标访问不安全?
看起来客户端光标正在为由CP填充的ashmem位置持有fd。 这是服务器(提供程序)死亡时客户端被杀死而不是引发诸如Binders之类的异常的原因吗?
Cursor
是不安全的。 尽管我认为大多数时候Cursor
仅用于对数据的“读取访问”,但它们比这更复杂。
简短说明在描述Cursor
的Android文档中:
该接口提供对数据库查询返回的结果集的随机读写访问。
因此, Cursor
不仅仅是保存在对象中的数据。 它们通过数据库连接将您放在ResultSet
。 ResultSet
使用JDBC访问数据库。 因此, Cursor
仅充当“ Java友好”数据库调用。 这是关于ResultSet
文档的Android:
通过适当的getter方法读取数据时,JDBC驱动程序将从数据库检索的SQL数据映射到应用程序调用的方法所隐含的Java类型。 JDBC规范有一个表,用于从SQL类型到Java类型的映射。
ResultSet
保持与数据库的连接。 数据未“复制”到接口中( Cursor
和ResultSet
都是接口,而不是对象;某些实现可能会复制数据,但我尚未对其进行测试,因为通过关闭的Connection
保持Statement
和ResultSet
资源打开可能会导致数据库资源问题)。
Java提供接口来获得JDBC对ResultSet
数据库中“结果集表”的访问,如Java文档中所述:
代表数据库结果集的数据表,通常通过执行查询数据库的语句来生成。
http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
您无法为因数据库中的ResultSet
表没有连接而死亡的ContentProvider提供“数据库访问”,因此应该处理Cursor
。
编辑:
有评论指出,Android不使用JDBC' or
ResultSet'-SQLite的Android实现与JDBC非常相似,其概念在本质上是相同的,没有方便的名称和描述。
Android使用自定义实现的事实使问题的描述更加困难,尽管我应该在原始帖子中对此进行引用。 如果需要更详细的参考和信息,这是有关JDBC状态和Android中SQLite接口实现的Google Groups线程:
https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw
从讨论中,您可能会向Joerg Pleumann询问更多详细信息...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.