1. 程式人生 > >Android app中的so庫和CPU架構

Android app中的so庫和CPU架構

應用 path 自己的 build 更新 這也 類型函數 eclips tro

一.android目前有幾種cpu架構?

早期的Android系統幾乎只支持ARMv5的CPU架構,目前支持七種CPU架構:ARMv5,ARMv7 (從2010年起),x86 (從2011年起),MIPS (從2012年起),ARMv8,MIPS64和x86_64 (從2014年起),每一種都關聯著一個相應的ABI。對應的ABI依次是:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64,對應Android app工程中so庫的不同目錄。

二.需要每種架構的so庫都放全嗎?

看so庫的來源,是第三方提供的,還是自己開發的。

1.倘若是集成第三方sdk,最好將它提供的都拷貝到項目中。(但是基本很少提供全面so庫支持的)

2.倘若是自己開發的 ,那就根據自己的情況,編譯出對應版本的so庫。

三.每種機型只能加載一種適合自己版本的so庫嗎?

很多設備都支持多於一種的ABI。例如ARM64和x86設備也可以同時運行armeabi-v7a和armeabi的二進制包。但最好是針對特定平臺提供相應平臺的二進制包,這種情況下運行時就少了一個模擬層(例如x86設備上模擬arm的虛擬層),從而得到更好的性能(歸功於最近的架構更新,例如硬件fpu,更多的寄存器,更好的向量化等)。

四.如何查看當前設備支持那些版本的so庫?

可以通過Build.SUPPORTED_ABIS得到根據偏好排序的設備支持的ABI列表。但你不應該從你的應用程序中讀取它,因為Android包管理器安裝APK時,如果在對應的lib/ABI目錄中存在.so文件的話,會自動選擇APK包中為對應系統ABI預編譯好的.so文件。

五.不同的開發環境so庫應該放在哪裏?

  • Android Studio工程放在jniLibs/ABI目錄中(當然也可以通過在build.gradle文件中的設置jniLibs.srcDir屬性自己指定)

  • Eclipse工程放在libs/ABI目錄中(這也是ndk-build命令默認生成.so文件的目錄)

  • AAR壓縮包中位於jni/ABI目錄中(.so文件會自動包含到引用AAR壓縮包的APK中)

  • 最終APK文件中的lib/ABI目錄中

  • 通過PackageManager安裝後,在小於Android 5.0的系統中,.so文件位於app的nativeLibraryPath目錄中;在大於等於Android 5.0的系統中,.so文件位於app的nativeLibraryRootDir/CPU_ARCH目錄中。

六.為什麽一般的項目中只看到armeabi文件夾?

因為所有的x86/x86_64/armeabi-v7a/arm64-v8a設備都支持armeabi架構的.so文件。 mips和mips64是不支持armeabi架構的.so文件的,不過MIPS是一種高性能的嵌入式CPU構架,其出發點是高性能,主要用於路由器、貓等,基本在手機上不使用

七.是不是只放一種armeabi就夠了?

事實上並不是:這不只影響到函數庫的性能和兼容性。x86設備能夠很好的運行ARM類型函數庫,但並不保證100%不發生crash,特別是對舊設備。64位設備(arm64-v8a, x86_64, mips64)能夠運行32位的函數庫,但是以32位模式運行,在64位平臺上運行32位版本的ART和Android組件,將丟失專為64位優化過的性能(ART,webview,media等等)。

八.不同Android版本系統拷貝不同目錄so庫的差異

工程項目中,有armeabi 、armeabi-v7a兩個文件夾,而兩個文件夾中的庫文件不一樣,編譯運行的時候,報錯java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader

原因分析

在android APK的根目錄有一個libs文件夾,此文件夾下包含了armeabi 、armeabi-v7a兩個文件夾,有時候會有x86的;一般c代碼編譯成的各種.so庫就會放在這兩個文件夾中。

armeabi和armeabi-7a是表示cpu的類型,一般的手機或平板都是用arm的cpu,armeabi是針對普通的或舊的arm cpu,armeabi通用性強,但速度慢;armeabi-v7a是針對有浮點運算或高級擴展功能的arm cpu,速度快

android的APP在安裝時,會將APP中的so庫拷貝到一個指定的目錄(ApplicationInfo.nativeLibraryDir),運行時就在這個指定的目錄下查找對應的so庫。查找不到則會報錯。

  1. 在android4.4以下版本的安裝過程中的,是先把所有so庫全部尋找出來,然後優先列出cpu類型(通過ro.product.cpu.abi屬性獲得)目錄下的so庫,如果有其他的cpu類型下有跟手機cpu類型名稱不一致的so庫,則會將兼容cpu架構(通過ro.product.cpu.abi2屬性獲得)的另外的庫也列出來。將列出來so庫全部拷貝的系統指定目錄,以供運行時加載。 即在android4.4以下版本,一個so庫只要在 ro.product.cpu.abi和ro.product.cpu.abi2屬性目錄下至少存在一個就可以了。在android4.4以下的arm架構的設備 ro.product.cpu.abi的屬性通常是armeabi-v7a, ro.product.cpu.abi2的屬性值是armeabi,並且armeabi-v7a設備一定兼容armeabi。但不排除某些設備的ro.product.cpu.abi的屬性為armeabi。

  2. 在android5.0及以上,由於增加了arm64的支持,app安裝時的so庫拷貝代碼也修改了。修改成只拷貝一個最合適的目錄下的so庫到系統指定目錄。 在arm架構下,64位cpu的優先級是arm64-v8a > armeabi-v7a > armeabi,32位cpu的優先級是armeabi-v7a > armeabi ,優先級可通過ro.product.cpu.abilist屬性查看。由於android5.0是拷貝整體目錄,所以在每一個目錄下的,都必須要有完整的so,即所有app需要so庫都要有。例如64位的cpu的設備上,
    如果app目錄裏存在arm64-v8a子目錄,則只拷貝該目錄下的so庫,其他目錄的so,即使名稱不一樣,也不拷貝,如果arm64-v8a子目錄的so庫不全,則會報錯。

解決方法

  1. apk中要麽增加armeabi文件夾,需要註意的是,假如增加armeabi文件夾,armeabi-v7a裏面的so庫一定需要全部拷貝過來,否則還是會報錯。

  2. 可以刪除了armeabi-v7a文件夾,保留armeabi文件夾。

Android app中的so庫和CPU架構