1. 程式人生 > >Android的.so檔案及常見問題彙總

Android的.so檔案及常見問題彙總

早期的Android系統幾乎只支援ARMv5的CPU架構,你知道現在它支援多少種嗎?7種!

Android系統目前支援以下七種不同的CPU架構:

ARMv5,ARMv7 (從2010年起),

x86 (從2011年起),

MIPS (從2012年起),

ARMv8,MIPS64和x86_64 (從2014年起),

每一種都關聯著一個相應的ABI。

應用程式二進位制介面(Application Binary Interface)定義了二進位制檔案(尤其是.so檔案)如何執行在相應的系統平臺上,從使用的指令集,記憶體對齊到可用的系統函式庫。在Android系統上,每一個CPU架構對應一個ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。




接下來我們去找小米手機4的架構

小米4採用的處理器的型號是高通驍龍801。具體的關於這款處理器的特徵是:主頻為2.5GHz、基於頂級Krait 400核心架構和28nm工藝,四核,同時搭載Adreno 330圖形處理器,在高通驍龍805上市之前,是安卓機搭載的最好的處理器。

Krait是美國高通公司基於ARMv7-A指令集、自主設計的採用28納米工藝的全新處理器微架構。(百度百科)

因此應該引用 armeabi-v7a 資料夾下的so檔案




一.我們需要每種版本的so庫都放全嗎?

1.看你的so庫的來源,是第三方提供的,還是自己開發的。倘若你是集成了某些第三方的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檔案。

六.那我們是不是隻放一種armeabi就夠了?

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

七.so庫開發過程中的一些錯誤彙總!(後續補充)

基本上大部分關於so庫的錯誤 都是   Java.lang.UnsatisfiedLinkError

官方解釋     Throw if the java Virtural Machine cannot find an appropriate native-language definition of method declared native意思就是JVM找不到native method的native實現!
所以看到這個錯誤,一般常見的幾種情況分析。

1、低階錯誤——根本木有SO,你載入個球啊!

code     System.loadLibrary(Bugly);
libs     空
執行裝置     Android ARM裝置
執行結果     Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly.so”
原因分析     apk安裝時,系統會把apk中libs目錄下armeabi的SO拷貝到應用的私有目錄下。所以libs裡沒有放入SO,執行時肯定找不到SO。
修復方式     新增SO:libs\armeabi\libBugly.so或載入程式碼註釋掉://System.loadLibrary(Bugly) ;

2、進階錯誤——根本木有X86的SO,在X86的裝置上你載入個球啊!

code     System.loadLibrary(Bugly);
libs     libs\armeabi\libBugly.so
執行裝置     Android X86裝置
執行結果     Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly.so”
原因分析     apk安裝時,x86裝置上系統會把apk中libs目錄下x86的SO,拷貝到應用的私有目錄下。雖然libs下有armeabi的SO,但沒有放入x86的SO,執行時還是找不到libbugly.so。
修復方式     新增SO:libs\x86\libBugly.so或載入程式碼註釋掉://System.loadLibrary(Bugly) ;

3、大坑——尼瑪,好難發現!

libs     libs\armeabi\libBugly.solibs\armeabi\libBugly2.solibs\armeabi-v7a\libBugly.so
執行裝置     Android ARMv7裝置
執行結果     Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly2.so”
原因分析     apk安裝時,系統會把apk中libs目錄下armeabi-v7a整個目錄下的SO拷貝到應用的私有目錄下。因為armeabi-v7a下沒有放入libBugly2.so,執行時找不到libBugly2.so。不同的工具相容的CPU架構不一致,就容易出這個錯誤了!例如:
libBugly.so提供armeabi、armeabi-v7a、x86三種。
但其它產品可能只提供了armeabi。
如果把這些so都直接拷貝進apk,就會因為上述的原因直接crash,會誤以為該Crash是因為不同產品的so不能相容導致的!
修復方式     新增SO:libs\armeabi-v7a\libBugly2.so或直接刪除armeabi-v7a目錄,arm裝置上系統會自動選擇armeabi

4、天坑——尼瑪,巨難發現!

java.lang.UnsatisfiedLinkError中couldn’t find “XX.so”的佔比非常高,上面提的三個場景都是這種錯誤!
但你見過下面這種錯誤嗎?
java.lang.UnsatisfiedLinkError:dlopen failed: “**/*/arm/*.so” has unexpected e_machine: 3
code     if(getArch().contain(“arm”)){//只在arm下載入System.loadLibrary(Bugly) ;}
libs     libs\armeabi\libBugly.so 坑爹實習生放入了x86編譯的libBugly.so(同名很容易出錯)
執行裝置     Android ARM裝置
執行結果     Crash!java.lang.UnsatisfiedLinkError: dlopen failed: “/data/app/com.tencent.bugly.crashreport.demo-2/lib/arm/libBugly.so” has unexpected e_machine: 3
原因分析     apk安裝時,系統把armeabi下的libBugly.so放入應用的私有目錄中了!但這個libBugly.so不是arm的,而是x86編譯的libBugly.so執行時,系統檢察ELF檔案中的e_machine欄位的值,跟arm的不匹配,就會丟擲這個異常了!

5 java.lang.UnsatisfiedLinkError:No implementation found for XXX

這種錯誤也是醉了,說是要建立跟c/cpp寫的程式碼一樣的包名和java檔案

這個so庫的錯誤是我這幾天在做騰訊雲視訊直播的時候出現的一些問題,他們的sdk(1.8.2版本)裡面的問題是:sdk裡面提供的so庫不全,導致出現各種問題。基本上面都介紹到了。