在Android平台上(在ICS上确认),如果内容提供者在客户端处于查询中间时死亡(即具有打开的游标),则框架决定终止持有打开游标的客户端进程。
当我尝试使用在执行查询后休眠的下载管理器查询时,这是一个logcat输出。 “睡眠”是为了重现这个问题。你可以想象当提供者在正确/错误的时间死亡时,它会在常规用例中发生。然后杀死com.android.media(托管downloadProvider)。
“Killing 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这样的异常吗?
答案 0 :(得分:-1)
Cursor
不安全。虽然我认为大部分时间Cursor
仅用于&#34;读访问&#34;对于数据,它们比这更复杂。
简短说明位于描述Cursor
:
此接口提供对结果集的随机读写访问 由数据库查询返回。
所以Cursor
不仅仅是对象中保存的数据。它们通过数据库连接在ResultSet
中保留您的位置。 ResultSet
使用JDBC访问数据库。所以Cursor
只是作为一个&#34; Java友好&#34;数据库调用。以下是ResultSet
文档的Android:
通过适当的getter方法读取数据时,JDBC驱动程序 将从数据库检索到的SQL数据映射到隐含的Java类型 通过应用程序调用的方法。 JDBC规范有一个 从SQL类型到Java类型的映射表。
ResultSet
保持与数据库的连接。数据未被复制&#34;进入界面(Cursor
和ResultSet
都是接口,而不是对象;有些实现可能会复制数据,但我还没有对其进行测试,因为留下了Statement
和{{1}通过关闭的ResultSet
打开资源会导致数据库资源问题。
Java提供了获取JDBC访问结果集表的接口&#34;在这里的Java文档中描述的Connection
的数据库中:
表示数据库结果集的数据表,通常是 通过执行查询数据库的语句生成。
http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
您无法提供&#34;数据库访问&#34;由于数据库中ResultSet
表没有连接而导致已死亡的ContentProvider,因此应处理ResultSet
。
编辑:
一条评论表明Android不使用Cursor
ResultSet` - SQLite的Android实现与JDBC非常相似,如果没有方便的名称和描述,概念基本相同。
Android使用自定义实现的事实使得问题的描述更加困难,尽管我应该在我的原始帖子中引用它。如果需要更详细的参考和信息,以下是关于JDBC状态和Android中SQLite接口实现的Google Groups线程:
https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw
从讨论中,你可能会问Joerg Pleumann更多细节......