一、概述
本節介紹一下so的加載原理,促使我寫這個小節的原因有兩點:
1.可以在給App瘦身的時候提供參考依據
2.可以給so插件化提供參考依據
下面就開始看so的加載原理吧。
二、so加載原理分析
2.1.so的編譯類型
在Android中只支持三種CPU架構:x86體系、mips體系、arm體系。而當前主流的是arm體系,mips體系和x86體系基本上已經被淘汰了。所以我們在做App瘦身的時候基本上可以不用考慮x86和mips架構,光從這一點就能為apk節省不少體積。
因為arm體系的CPU架構是當前主流的,所以下面只所arm體系的架構
arm體系的CPU架構目前分為兩種,一種32位的,另一種是64位的。
2.1.1.
armeabi/armeabi-v7a:這兩個架構都是arm類型的,主要用於Android4.0之后的CPU是32位的。其中armeabi是比較老的一個版本,其缺少對浮點數計算的硬件支持,基本已經被淘汰了,可以不用考慮。
arm64-v8a:這個架構是arm類型,主要用於Android5.0之后,CPU是64位的。
這是一個常見的目錄:
在Android上啟動一個App,系統都會為每個App創建一個虛擬機。Android 64位系統加載32位的so或者App,在創建一個64位虛擬機以外還會創建一個32位的虛擬機用來加載32位的so或者App。所以根本沒有必要每一個CPU架構都支持,因為Android系統是向下兼容的。只需要要保留一個armeabi-v7a的CPU架構就可以了,64位的系統會在32位的虛擬機上加載它。這樣可以大大的減少apk的體積。
2.2.so的加載流程
1.假設我們在jniLibs目錄下創建兩個目錄arm64-v8a和armeabi-v7a。加載的時候優先會加載arm64-v8a,而不會加載armeabi-v7a。所以我們只需要在armeabi-v7a的目錄下放so包即可。
2.2.3.加載so的兩種方式
1.System.loadLibrary(path),只能加載jniLIbs目錄下的so
2.System.load(path),可以加載任意路徑下的so
這兩種方式最終都會調用Android底層的dlopen來打開so
2.2.4、動態加載so
動態加載so:只要so文件不是app運行的時候立馬加載,我們都可以把so放到服務器上慢慢的下載。
我們可以使用System.load方法加載任意路徑下的so文件,所以我們在發布app的時候不需要讓so和app一塊打包,只需要在用到的時候從服務器上下載下來即可。從這種角度來說,只要我們的app不是打開后立馬加載so,我們就沒有必要把so文件和app一塊打包。一旦apk中沒有so包,這可以極大的縮小apk的體積。