android?sharedUserId?使用知識(shí)盲點(diǎn)解析
1. 背景
由于在工程中使用了 SPI 機(jī)制,通過 ServiceLoader 的配合來完成模塊間的通信。但是突然收到線上客戶反饋使用了 SDK 后無法進(jìn)行模塊加載,導(dǎo)致部分功能異常。
2. 分析排查
借助客戶提供的測(cè)試包進(jìn)行 debug 調(diào)試,發(fā)現(xiàn)在調(diào)試到 ServiceLoader.load() 方法時(shí)確實(shí)無法加載到對(duì)應(yīng)的模塊配置。查看 ServiceLoader 的狀態(tài)信息如下:
其中的 loader 是 LoadApk$WarningContextClassLoader 對(duì)象,而正常情況下是 DexPathClassLoader。
2.1 查看 ServiceLoader.loader 定義
ServiceLoader API 文檔:developer.android.com/reference/j…
根據(jù)接口定義 load 方法會(huì)根據(jù)指定的 serviceType 創(chuàng)建新的 ServiceLoader 對(duì)象返回,ServiceLoader 內(nèi)部根據(jù)當(dāng)前線程對(duì)應(yīng)的 ContextClassLoader 對(duì)象去加載配置,所以到這里可以分析到 load 方法的加載結(jié)果會(huì)受 ContextClassLoader 的影響,進(jìn)一步推理可能收到插件化、熱修復(fù)等框架影響,確認(rèn)后并沒有使插件化、熱修復(fù)等框架。
2.2 WarningContextClassLoader 為何物?
查找 Android famework 源碼,找到 WarningContextClassLoader 是定義在 LoaderApk 文件中的內(nèi)部類(部分版本是 ActivityThread 類中的內(nèi)部類)。
private void initializeJavaContextClassLoader() { IPackageManager pm = ActivityThread.getPackageManager(); android.content.pm.PackageInfo pi = PackageManager.getPackageInfoAsUserCached( mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.myUserId()); if (pi == null) { throw new IllegalStateException("Unable to get package info for " + mPackageName + "; is package not installed?"); } /* * Two possible indications that this package could be * sharing its virtual machine with other packages: * * 1.) the sharedUserId attribute is set in the manifest, * indicating a request to share a VM with other * packages with the same sharedUserId. * * 2.) the application element of the manifest has an * attribute specifying a non-default process name, * indicating the desire to run in another packages VM. */ boolean sharedUserIdSet = (pi.sharedUserId != null); boolean processNameNotDefault = (pi.applicationInfo != null && !mPackageName.equals(pi.applicationInfo.processName)); boolean sharable = (sharedUserIdSet || processNameNotDefault); ClassLoader contextClassLoader = (sharable) ? new WarningContextClassLoader() : mClassLoader; Thread.currentThread().setContextClassLoader(contextClassLoader); } private static class WarningContextClassLoader extends ClassLoader { private static boolean warned = false; private void warn(String methodName) { if (warned) { return; } warned = true; Thread.currentThread().setContextClassLoader(getParent()); Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " + "The class loader returned by " + "Thread.getContextClassLoader() may fail for processes " + "that host multiple applications. You should explicitly " + "specify a context class loader. For example: " + "Thread.setContextClassLoader(getClass().getClassLoader());"); } ... }
在應(yīng)用創(chuàng)建時(shí)會(huì)調(diào)用 ActivityThread 類中的 attach 方法中,attach 方法進(jìn)而調(diào)用 LoadedApk 類中的 makeApplicationInner() 用于創(chuàng)建對(duì)應(yīng)的 Application 對(duì)象。在 makeApplicationInner() 方法的內(nèi)部調(diào)用 initializeJavaContextClassLoader 方法創(chuàng)建對(duì)應(yīng)的 ContentClassLoader 對(duì)象,在 initializeJavaContextClassLoader 方法的內(nèi)部可以看到,如果當(dāng)前 App 在 manifest 中設(shè)置 sharedUserId 屬性,則當(dāng)前應(yīng)用使用的是 WarningContextClassLoader。下面我們就是查看 App 中的配置。
最終驗(yàn)證了我們的猜想,使用 demo 設(shè)置 sharedUserId 屬性問題可正常復(fù)現(xiàn)。
2.3 sharedUserId 屬性
查看官方文檔該屬性配置 API 級(jí)別 29 中已棄用此常量。共享用戶 ID 會(huì)在軟件包管理器中導(dǎo)致具有不確定性的行為。因此,強(qiáng)烈建議您不要使用它,并且我們?cè)谖磥淼?Android 版本中會(huì)將其移除。
2.總結(jié)
排查問題還是比較費(fèi)神,在沒有明顯錯(cuò)誤的時(shí)候,只能針對(duì)每個(gè)可疑的信息去分析,期望發(fā)現(xiàn)蛛絲馬跡。
以上就是android sharedUserId 使用知識(shí)盲點(diǎn)解析的詳細(xì)內(nèi)容,更多關(guān)于android sharedUserId 知識(shí)盲點(diǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android開發(fā)教程之使用listview顯示qq聯(lián)系人列表
這篇文章主要介紹了android使用listview顯示qq聯(lián)系人列表的示例,需要的朋友可以參考下2014-02-02Android編程實(shí)現(xiàn)基于局域網(wǎng)udp廣播自動(dòng)建立socket連接的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)基于局域網(wǎng)udp廣播自動(dòng)建立socket連接的方法,涉及Android使用udp廣播實(shí)現(xiàn)socket通訊的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android未讀消息拖動(dòng)氣泡示例代碼詳解(附源碼)
這篇文章主要介紹了Android未讀消息拖動(dòng)氣泡示例代碼詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Android 二維碼 生成和識(shí)別二維碼 附源碼下載
這篇文章主要介紹了Android 生成和識(shí)別二維碼的方法,提供源碼下載,需要的朋友可以參考下。2016-06-06Android利用ViewPager實(shí)現(xiàn)帶小圓球的圖片滑動(dòng)
這篇文章主要為大家詳細(xì)介紹了Android利用ViewPager實(shí)現(xiàn)帶小圓球的圖片滑動(dòng),并且只有第一次安裝app時(shí)才出現(xiàn)歡迎界面具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11Android編程實(shí)現(xiàn)ListView滾動(dòng)提示等待框功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)ListView滾動(dòng)提示等待框功能,結(jié)合實(shí)例形式分析了Android ListView滾動(dòng)事件相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02