use*_*992 5 android robustness android-contentprovider ashmem
在 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 }
Run Code Online (Sandbox Code Playgroud)
这是一个政策决定还是提供者死亡后游标访问不安全?
看起来客户端光标持有一个由 CP 填充的 ashmem 位置的 fd。这就是当服务器(提供者)死亡时客户端被杀死而不是抛出像 Binders 这样的异常的原因吗?
Jim*_*Jim -1
是Cursor不安全的。虽然我认为大多数时候Cursors 仅用于对数据的“读访问”,但它们比这更复杂。
Android 文档中有简短的解释,描述了Cursor:
该接口提供对数据库查询返回的结果集的随机读写访问。
所以Cursors 不仅仅是对象中保存的数据。ResultSet它们通过数据库连接保持您的位置。使用ResultSetJDBC 访问数据库。因此,它Cursor仅充当“Java 友好”数据库调用。以下是 Android 相关文档ResultSet:
当通过适当的 getter 方法读取数据时,JDBC 驱动程序将从数据库检索的 SQL 数据映射到应用程序调用的方法所隐含的 Java 类型。JDBC 规范有一个用于从 SQL 类型到 Java 类型的映射表。
保持ResultSet与数据库的连接。数据不会“复制”到接口中( 和Cursor都是ResultSet接口,而不是对象;某些实现可能会复制数据,但我没有测试它,因为通过关闭保留Statement和打开资源可能会导致数据库资源问题)。ResultSetConnection
Java 提供了接口来获取对数据库中“结果集表”的 JDBC 访问,如ResultSetJava 文档中所述:
表示数据库结果集的数据表,通常是通过执行查询数据库的语句生成的。
http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
ResultSet您无法向已死亡的 ContentProvider 提供“数据库访问”,因为数据库中的表没有连接,因此Cursor应将其丢弃。
编辑:
一条评论表明 Android 不使用JDBC' orResultSet` - SQLite 的 Android 实现与 JDBC 非常相似,概念本质上是相同的,只是没有方便的名称和描述。
Android 使用自定义实现这一事实使得问题的描述变得更加困难,尽管我应该在我原来的帖子中引用这一点。如果需要更详细的参考和信息,这里是关于 JDBC 状态和 Android 中 SQLite 接口实现的 Google Groups 主题:
https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw
从讨论中,您可能可以向 Joerg Pleumann 询问更多细节......
| 归档时间: |
|
| 查看次数: |
1694 次 |
| 最近记录: |