[Android]用架構師角度看插件化(2)-Replugin 惟一hook點

你們好,我係蒼王。
java

如下是我這個系列的相關文章,有興趣能夠參考一下,能夠給個喜歡或者關注個人文章。安全

[Android]用架構師角度看插件化--章節列表
架構


Replugin,爲什麼我選擇要研究這個的插件呢?很大的緣由是由於它的介紹中說明,他只會有一個hook點。app


一.Hook

hook點是什麼?框架

咱們入門Android的時候,必定會看到過這個圖,可是你肯定深入瞭解到這個圖的嗎?組件化


咱們試着換着思惟,用組件化的角度去看這張圖,你會發現其層級依賴關係,與組件化的工程是很是相似的。(固然你看得角度不一樣,我只能說是相似)學習

假若你用插件的思想來看,咱們上層的衆多應用(Applications)就是做爲framewrok層的插件同樣的存在。(Framework做爲宿主同樣的存在,只是它是對於應用們,他說了算,基於安全管理和效率,他能限制大家獲取資源的權限和方法)插件

而後咱們想要在獨自的應用中作得像Framework層同樣的加載應用,咱們自己就享用了Framework層對資源等的加載機制。若是咱們想要將某些資源加載,加載驗證,權限限制等繞開,運用到手機自己Framework來完成,就會涉及到hook了。3d

以我理解:hook,當Framework運行時,攔截並替換掉Framework層中某些原生的方法或對象,讓其運行到咱們想要的效果。cdn


滴滴的VirtualApk 會hook掉AMS(ActivityManagerService)和Instumentation,這兩個Framework的文件很是重要,AMS是四大組件的入口,管理生命週期,管理應用通訊等,Instumentation管理了Activity的生命週期的調用。有興趣能夠深刻去看這兩個Framework文件。而其餘舊式插件化,還會hook掉一下Service,Broadcast的機制。

而Replugin卻走的是徹底和傳統插件化不一樣的路,它hook掉的是ClassLoader,並且它只有惟一的hook點。


hook爲什麼會不安全?

就是攔截和替換原生機制,由於Android的機型太多了,並且是開源的,那麼各個廠商定製Rom的修改,不一樣版本的適配也是很是大的阻礙,假若替換掉某些廠商修改Google原生Android的源碼裏面的方案,2️⃣恰好hook點沒有兼容這方面的源碼,就有引發hook失敗或者崩潰的可能性。

意味着hook點越少,其可能產生修改的代碼會變小,維護的代價會變小,耗損的人力資源就會變少,整個用戶體驗就會提高。

架構的標準,是要懂得,衡量 時間+空間+效率。惟一hook點,暫時Replugin應該是插件化hook點的極致了。



二.ClassLoader

對於Android 的ClassLoader,請認真仔細看下圖,一張圖爲你解答各類疑問。

此圖很是形象的說明Android裏面ClassLoader的架構。


這裏通常插件化框架,都是使用DexClassLoader動態加載dex文件。

DexClassLoader能夠加載apk,dex,jar,還有zip後綴格式的文件,其最終應該是加載dex文件,這也是我QQ羣中驗證問題的答案。

BaseDexClassLoader,裏面有一個DexPathList對象,是用來保存dex的列表的,而查詢dex裏面的資源、class都是在這個列表中遍歷dex對象。

而Replugin是特別的其使用自定義的PathClassLoader來加載apk中的dex,其有別於其餘插件框架。


三.惟一hook點

咱們看一下Replugin的加載過程。

用的是官網的replugin-host-library爲例子

Application中attachBaseContext是最快執行的,其調用了Replugin.App.attachBaseContext方法


他會調用到PMF這個類init方法,PMF是框架和住程序接口


其裏面會調用pluginManger的初始化,還有PatchClassLoaderUtils.patch的方法。


PatchClassLoaderUitls這個類是修改宿主和私有屬性的位置,其實就是那個惟一的hook點的位置


能夠看到在patch中須要獲取到整個application的context對象。


而後生成本身的classLoader對象,去hook掉mClassLoader對象,FieldUtils是對Java反射機制的封裝,之後使用到發射的時候,能夠參考一下這裏的封裝,感受是迄今看到衆多插件化的封裝最完善的。


這裏的對參數的說明很清晰,最終會返回RePluginClassLoader對象。



這裏調用到RepluginClassLoader裏面,copyFromOrginal會將一些須要更改的屬性去掉final屬性,才能開始修改。initMethods,反射來替換掉ClassLoader的方法


裏面替換掉四個方法,findResource和findResources是資源的獲取,findLibrary是庫獲取,getPackage就是獲取包信息了。

這裏MethodUtils是方法反射的封裝,也是封裝得很是好。


在Android源碼中,是經過DexPathList中讀取資源,Resource是以URL格式返回,而lib庫是用String返回


包獲取是在classLoader中完成的


這裏你會發現有點矛盾的地方,由於有可能不是那麼容易一會兒能看明。

咱們前面看到須要反射出一些BaseDexLoader的一些方法


可是你看到其繼承調用的時候,卻使用瞭如出一轍的方法,這樣不就用瞭如出一轍的流程了?這有何意義?


這裏其實意義就在於其傳入的mOrig參數,這個參數是classLoader的對象,而不一樣插件間都有classloader,那麼其分別調用插件間的classloader資源的時候,就須要在這裏攔截調用。


以上就是對Replugin的惟一hook點的分析。

值得借鑑的地方。

(1)惟一hook點,是用hook掉足夠大的ClassLoader對象,來讓資源加載獲得更加便利。

(2)Java反射機制的整合FieldUtils域反射封裝和MethodUtils方法反射封裝。


這裏發一條廣告,我創立了一個小密圈。

天天會分享java基礎,組件化插件化相關,音視頻開源項目分享。在管理員們的努力下,提供了動腦學院vip,慕課網的Android付費資源。

最重要,帶有羣員們珍貴的分析和點評。

還有最新插件化框架的分析和運用,組件化架構技巧的分享,都盡在這裏。

不須要一頓飯的價錢 ,68/一全年的學習資料。

付費是真乾貨,真正節省時間的通往技術的途徑。

來到這裏但願影響你的不僅是技術提高,並且是人生的架構的導向。


成立兩週已經有超過190+的小夥伴加入了咱們的行列了,而且持續增長,讓咱們一塊兒成長,羣內還有不定時福利,包括原創書籍的福利哦。


我創建了一個關於Android架構學習的羣,裏面能夠進一步進行組件化學習的交流。

羣號是316556016,也能夠掃碼進羣。我在這裏期待大家的加入!!!

相關文章
相關標籤/搜索