動態加載dex這個技術屬於看上去高大上,原理很簡單,做起來很崩潰的一個玩意。
首先要說的是,這個技術肯定是得掌握才行的。APK加固,熱修復,插件化,這些個最近幾年比較高大上的玩意,基礎原理都是從動態加載dex開始的。有很多博客做過這個課題,有很多寫的不錯的博客,我就從自己學習的流程給大家說說這玩意。
apk編流程譯
首先要理解APK的一個編譯流程,google的官網上有着詳細的一張圖,我選了一個博客上精簡過的。
打包整體流程:
- 打包資源文件,生成R.java文件
- 處理aidl文件,生成相應的.java文件
- 編譯工程源xs碼,生成相應的class文件
- 轉換所有的class文件,生成classes.dex文件
- 打包生成apk
- 對apk文件進行簽名
- 對簽名後的apk進行對齊處理
需要注意點的就是appt打包時候是運行兩次,一次編譯是將class文件變成.dex一次是把資源文件編譯出來。
dex文件的65535根本原因是,dex中統計method個數的類型是個short!無符號邊界的話就是就是可以存儲最大65535個方法數。
dex文件的結構
- 8位字節的二進制流文件
- 各個數據緊密排列,無間隙,減少了文件體積,加快加載速度
- 整個工程的類信息都存放在一個dex文件中(不考慮dex分包的情況下)
優勢 :1.優化常量池 2.dex文件的頭文件與索引區部分,dvm可通過這兩部分快速查找到對應類及數據
類加載器
這個玩意就是動態加載的核心了
Android加載器
1.PathClassLoader用來加載Android系統類和應用的類和已安裝好的APK
2.DexClassLoader支持加載APK、DEX和JAR,也可以從SD卡進行加載。
說幾個比較需要注意的點。這兩個類加載器的區別在於,DexClassLoader可以傳遞一個叫optimizedDirectory的參數。從名字上的意思是提供一個存放優化後Dex的文件夾。Dex會經過一次優化,變成ODex,方便內存查找。意思就是DexClassLoader可以解壓,PathClassLoader不帶解壓功能,所以只能加載已安裝好的APK,因爲安裝好的在緩存中有ODex。
另外一個重點就是類加載器是一個雙親委派機制。在加載一個類的時候,它會先讓它的父類去加載,如果父類沒有加載過,纔會自己去加載。作用就是,不會有重複的類被加載。這個機制很關鍵,QQ空間的熱修復方式就是利用了這點。他們把修復類放到Elements數組最前面,這樣有bug的Class就會因爲這個機制,不再被加載,就達到了修復的目的、
反射機制
這就是動態加載的另一個重要機制了。我一直相信,做好android一定要學好JAVA。用個人理解來說下原理:Java中一個.Class文件就是一個類,JVM是動態加載,一個.Class在被使用時纔會加載進內存中。當它被加載到內存後,分配空間還有它的引用。反射就是讓內存在已經加載的通過包名,類名去找到這個.Class文件,找到後返回它的引用。所以這個過程很耗資源。
如何寫一個反射的代碼網上很多,我就只聊一下我的理解。
Android中去動態加載時,記住先去用DexClassLoader把Dex加載完成,再去反射你要的類。如果要進行修復,那就去獲取Elements數組,把你的Dex與之前的Dex重新組合。加固的話就是先把Dex進行加密,然後在Application裏面,先解密,解密完成之後,在把Dex拼起來。