[英]android content provider robustness on provider crash
On android platforms (confirmed on ICS), if a content provider dies while a client is in the middle of a query (ie has a open cursor) the framework decides to kill the client processes holding a open cursor. 在android平台(在ICS上已确认)上,如果内容提供者在客户端处于查询中间(即具有打开的游标)时死亡,则框架决定杀死持有打开的游标的客户端进程。
Here is a logcat output when i tried this with a download manager query that sleeps after doing a query. 这是我使用下载管理器查询尝试执行此操作后休眠的logcat输出。 The "sleep" was to reproduce the problem.
“睡眠”是为了重现问题。 you can imagine it happening in a regular use case when the provider dies at the right/wrong time.
您可以想象,当提供者在正确/错误的时间死亡时,它会在常规用例中发生。 And then do a kill of com.android.media (which hosts the downloadProvider).
然后杀死com.android.media(托管downloadProvider)。
"Killing com.example (pid 12234) because provider com.android.providers.downloads.DownloadProvider is in dying process android.process.media" “杀死com.example(pid 12234),因为提供程序com.android.providers.downloads.DownloadProvider即将死于android.process.media”
I tracked the code for this in ActivityManagerService::removeDyingProviderLocked 我在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 }
Is this a policy decision or is the cursor access unsafe after the provider has died? 这是策略决定,还是提供者死亡后游标访问不安全?
It looks like the client cursor is holding a fd for an ashmem location populated by the CP. 看起来客户端光标正在为由CP填充的ashmem位置持有fd。 Is this the reason the clients are killed instead of throwing an exception like Binders when the server (provider) dies ?
这是服务器(提供程序)死亡时客户端被杀死而不是引发诸如Binders之类的异常的原因吗?
The Cursor
is unsafe. Cursor
是不安全的。 Although I think most of the time Cursor
s are used only for "read access" to data, they are more complex than that. 尽管我认为大多数时候
Cursor
仅用于对数据的“读取访问”,但它们比这更复杂。
The short explanation is in the Android docs that describes a Cursor
: 简短说明在描述
Cursor
的Android文档中:
This interface provides random read-write access to the result set returned by a database query.
该接口提供对数据库查询返回的结果集的随机读写访问。
So Cursor
s are not just data held in an object. 因此,
Cursor
不仅仅是保存在对象中的数据。 They hold your place in a ResultSet
through a database connection. 它们通过数据库连接将您放在
ResultSet
。 The ResultSet
uses JDBC to access a database. ResultSet
使用JDBC访问数据库。 So the Cursor
is acting only as a "Java friendly" database call. 因此,
Cursor
仅充当“ Java友好”数据库调用。 Here are the Android for the ResultSet
docs on that: 这是关于
ResultSet
文档的Android:
When reading data via the appropriate getter methods, the JDBC driver maps the SQL data retrieved from the database to the Java type implied by the method invoked by the application.
通过适当的getter方法读取数据时,JDBC驱动程序将从数据库检索的SQL数据映射到应用程序调用的方法所隐含的Java类型。 The JDBC specification has a table for the mappings from SQL types to Java types.
JDBC规范有一个表,用于从SQL类型到Java类型的映射。
The ResultSet
keeps a connection to the database. ResultSet
保持与数据库的连接。 The data is not "copied" into the interface (both Cursor
and ResultSet
are interfaces, not objects; some implementations may copy the data, but I haven't tested it because leaving Statement
and ResultSet
resources open through a closed Connection
can cause DB resource issues). 数据未“复制”到接口中(
Cursor
和ResultSet
都是接口,而不是对象;某些实现可能会复制数据,但我尚未对其进行测试,因为通过关闭的Connection
保持Statement
和ResultSet
资源打开可能会导致数据库资源问题)。
Java provides the interface to gain JDBC access to a "results set table" in the database for the ResultSet
as described in the Java docs here: Java提供接口来获得JDBC对
ResultSet
数据库中“结果集表”的访问,如Java文档中所述:
A table of data representing a database result set, which is usually generated by executing a statement that queries the database.
代表数据库结果集的数据表,通常通过执行查询数据库的语句来生成。
http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
You cannot provide "database access" to a ContentProvider that has died because there is no connection the ResultSet
table in the database, so the Cursor
should be disposed of. 您无法为因数据库中的
ResultSet
表没有连接而死亡的ContentProvider提供“数据库访问”,因此应该处理Cursor
。
EDIT: 编辑:
One comment suggests that Android does not use JDBC' or
ResultSet` - the Android implementation of the SQLite is a very similar implementation to JDBC, and the concepts are essentially the same without the convenient names and descriptions. 有评论指出,Android不使用
JDBC' or
ResultSet'-SQLite的Android实现与JDBC非常相似,其概念在本质上是相同的,没有方便的名称和描述。
The fact that Android uses a custom implementation makes the description of the problem more difficult, although I should have made reference to this in my original post. Android使用自定义实现的事实使问题的描述更加困难,尽管我应该在原始帖子中对此进行引用。 Here is the Google Groups thread on the status of JDBC and the SQLite interface implementation in Android, if more detailed references and information is required:
如果需要更详细的参考和信息,这是有关JDBC状态和Android中SQLite接口实现的Google Groups线程:
https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw
From the discussion, you could probably ask Joerg Pleumann for more details... 从讨论中,您可能会向Joerg Pleumann询问更多详细信息...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.