我系蒼王尤溜,歡迎關(guān)注的源碼分析的第五節(jié)即硼。
歡迎瀏覽我之前的文章彬向,有興趣可以參考一下兼贡,可以給個喜歡或者關(guān)注我的文章,謝謝娃胆。
[Android]如何做一個崩潰率少于千分之三噶應(yīng)用app(9)-Small插件化
Small插件化源碼分析--InstumentationWrapper生命周期
五.ReflectAccelerator的奏曲
這一節(jié)遍希,我們要分析Small真正實現(xiàn)的核心代碼
這個文件就是ReflectAccelerator的代碼。
其相關(guān)到resource里烦,dex凿蒜,lib替換的相關(guān)流程
1.這里需要大家對classloader有一個基本的認(rèn)識
Dalvik虛擬機如同其他Java虛擬機一樣,在運行程序時首先需要將對應(yīng)的類加載到內(nèi)存中胁黑。而在Java標(biāo)準(zhǔn)的虛擬機中废封,類加載可以從class文件中讀取,也可以是其他形式的二進制流丧蘸。
? PathClassLoader:它只能加載已經(jīng)安裝到 Android 系統(tǒng)中的 apk 文件虱饿,也就是 /data/app 目錄下的 apk 文件
? DexClassLoader: 可以加載 apk, jar 或者 dex 文件
而插件化真正用到的就是DexClassLoader,其繼承于ClassLoader触趴。
源碼在DexClassLoader源碼氮发,其源碼在dalvik虛擬機的目錄里面,所以platform里面無法看到全部的源碼冗懦。
我們從第一節(jié)啟動流程中有一個初略的說明爽冕,還是分別從resource,dex披蕉,lib的替換流程來分析吧
(1)我們首先是利用mergeResouce這個函數(shù)來加載資源resource的
我們需要自己新建一個AssetManager或者獲取Aplication的AssetManager颈畸。
addAssetPaths中,通過反射的方式來把資源路徑和assetManager替換成我們自己定義的資源
ensureStringBlocks來創(chuàng)建字符串資源池
新建弱引用集合Resources資源
4.4以上的版本没讲,通過反射一個新的ResourcesManager眯娱,用數(shù)組表獲取現(xiàn)在啟動應(yīng)用的資源列表。如果獲取不了會取出reourcesManager里面的mResourceReferences資源指向
4.4以下的版本爬凑,使用哈希表來獲取mActiviteResources活躍資源
通過遍歷資源Resources,來替換newAssetManger到mAssets屬性里面
異常會反射mResourcesImpl代理接口徙缴,來替換到mAssets里面
替換后,觸發(fā)資源的配置刷新嘁信,讓其可以生效
如果是5.0以上的系統(tǒng)于样,就需要清除應(yīng)用資源每個字節(jié)池里面的內(nèi)容疏叨。
Small里面,并沒有提供移除資源的方法穿剖,如果需要改寫蚤蔓,可以自己去添加一個方法。
(2)添加Dex的時候糊余,使用的是expandDexPathList的方法
其有少于9到13可以調(diào)用的方法秀又,還有4.0以上所調(diào)用的方法
先看一下9到13的方法
首先獲取mFiles mPaths mZips mDexs的屬性
替換掉全部的這些屬性的變量
通過expandArray調(diào)用System.arraycopy,來添加dexclassloader里面的這些屬性值贬芥,
當(dāng)push為true時涮坐,其排序是先將目標(biāo)的長度的elements寫入,再寫入原來已經(jīng)加載好的elements到后面
當(dāng)push為false時誓军,是先將已有elements寫入袱讹,然后將自己的寫到已有的之后
這里和MultiDex.java使用的是類似的替換方法
這里System.arraycopy的方法是會調(diào)用到native層去運行的昵时,從參數(shù)可以看出其運行規(guī)則
再看一下Android4.0以上的添加Dex方法,
其需要的是將Elemets的變量封裝一個Object的數(shù)組里面
Android4.0以上有DexPathList.java里面封裝了一個Element的類捷雕,用于保存Dex的信息
其makeDexElement的方法,就是用來封裝Element的表
獲取DexPathsList的Delement的類來動態(tài)新建一個Element壹甥。
使用fillDexPathList來反射pathList和dexElements的屬性救巷,再使用expandArray來添加資源到尾部
(3)通過expandNativeLibraryDirectories來添加lib的.so文件
android 9~13中,只是獲取libraryPathDeements的屬性句柠,然后獲取加載路徑列表浦译,然后把自定義的列表添加到原來的列表里面,需要用“/”來分隔
android14~22中溯职,是使用反射nativeLibraryDirectories的接口精盅,然后通過expandArray來寫入到library列表之后
android23以上,稍顯復(fù)雜谜酒,需要先索引到nativeLibraryDirectories目錄叹俏,然后再獲取natveLibraryPathElements的Element對象列表,然后通過封裝Element的列表對象僻族,然后再通過expandArray放到末尾
其加載的方法就到這里粘驰,然而RefectAccelerator還有一些比較特殊的方法
獲取ActvityThread,如果currentActivityThread存在就返回這個屬性述么,否則通過讀取mLoadedApk里面的mActivityThread來獲取
上一節(jié)InstrumentationWrapper的execStartActivity實際上也是通過ReflectAccelerator封裝的
android 9~20 包裝好types蝌数,然后通過getMethod反射獲取execStartActivity的方法,然后再通過反射再次自己的屬性值
反射獲取方法
android21以上原理和以上的以上度秘,只是參數(shù)不同而已
*****************這里是最后的福利******************
這里提供了sliceArray的方法顶伞,這個方法是用來刪除array里面的某個項的資源的。這個有什么用,這個對對自定義刪除dex枝哄,library都起到至關(guān)重要的作用,如果利用這個源碼就得大家深入去探究啦阻荒。我這邊已經(jīng)是完成了刪除resource挠锥,dex,library的源碼修改侨赡。
這節(jié)課程就到這里蓖租。
Small源碼分析暫時就到這里。
如果以后有時間會再去查看一下aapt等資源打包的流程羊壹。
下一節(jié)蓖宦,敬請期待!S兔ā稠茂!