2012-12-17 138 views
4

在android平臺上(在ICS上確認),如果內容提供者在客戶端處於查詢中間時死亡(即有一個打開的遊標),框架決定終止持有的客戶端進程一個打開的光標。安卓內容提供商在提供商崩潰時的健壯性

這是一個logcat輸出,當我嘗試這個下載管理器查詢後,進行查詢睡覺。 「睡眠」是爲了重現這個問題。當提供者在正確/錯誤的時間死亡時,您可以想象它會在常規用例中發生。然後殺死com.android.media(託管downloadProvider)。

「殺com。示例(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

logcat,請給我來源?以提供您所要求的SO社區的利益。 :) – t0mm13b

+0

編輯信息的問題! – user1298992

+0

最好提供logcat的完整輸出,一行是不夠的!以及你的問題的性質,這將推動評論/答案猜測它是什麼......基本上猜測,並可能導致這個問題的關閉,作爲*不建設性*或*太*本地化* ...... – t0mm13b

回答

-1

Cursor是不安全的。雖然我認爲大部分時間Cursor僅用於「讀取」數據,但它們比這更復雜。

簡短的解釋是,它描述了Android文檔一個Cursor

該接口提供對結果的隨機讀寫權限設置由數據庫查詢返回 。

因此Cursor s不只是數據保存在一個對象。他們通過數據庫連接在ResultSet中佔據您的位置。 ResultSet使用JDBC訪問數據庫。因此,Cursor僅作爲「Java友好」數據庫調用。下面是在Android用於在該ResultSet文檔:

當經由適當getter方法讀數據時,JDBC驅動 從數據庫中由該方法暗示 Java類型由被調用檢索的SQL數據映射應用。 JDBC規範有一個 表,用於從SQL類型到Java類型的映射。

ResultSet保持與數據庫的連接。數據不會被「複製」到接口中(CursorResultSet都是接口,而不是對象;有些實現可能會複製數據,但我沒有測試過,因爲通過關閉打開StatementResultSet資源會導致數據庫資源問題)。

Java提供的界面作爲Java文檔在此描述,以獲得爲ResultSet在數據庫JDBC訪問「的結果設定表」:

表示數據庫結果集的數據的表,該表通常是通過執行查詢數據庫的語句生成的 。

http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html

不能提供「數據庫訪問」到死了,因爲在數據庫中沒有連接ResultSet表ContentProvider的,所以Cursor應予以處置。

編輯:

一種意見認爲Android不使用JDBC' or ResultSet` - 安卓實施的SQLite是一個非常相似的實施JDBC和概念是基本上不便利的名稱和描述相同。

Android使用自定義實現的事實使問題的描述更加困難,雖然我應該在我的原始文章中引用此內容。下面是JDBC的狀態,並在Android的SQLite的接口實現了谷歌組線程,如果需要更詳細的參考資料和信息:

https://groups.google.com/forum/#!topic/android-developers/zz3qlNL2JDw

從討論中,你很可能要求約爾格Pleumann瞭解更多詳情...

+1

'android.database'軟件包(包括'SQLiteDatabase'和'SQLiteCursor')不使用JDBC或'ResultSet'接口。 – corsair992

+0

我更新了我的答案,以解決Android實現與標準JDBC的關係;它非常相似,所以在概念上我並沒有真正看到差異。 – Jim