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檔案的話,
四.不同的開發環境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庫不全,導致出現各種問題。基本上面都介紹到了。