1. 程式人生 > >安卓開發之so庫載入使用的那些坑

安卓開發之so庫載入使用的那些坑

世上本沒有路,踩坑的多了就把路填平了。

一、UnsatisfiedLinkError基本介紹

全名     java.lang.UnsatisfiedLinkError
官方解釋     Throw if the java Virtural Machine cannot find an appropriate native-language definition of method declared native意思就是JVM找不到native method的native實現!
   丟擲這異常,肯定是你載入SO的姿勢不對!

現在App很多功能都是通過整合第三方工具實現的,第三方工具很有可能在SO動態庫裡實現核心功能(Bugly提供的libBugly.so,能捕獲這類C/C++異常!),所以就算你不用NDK開發也一定會跟SO打交道,你確定你載入SO的姿勢都對了嗎?

二、錯誤場景分析

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、大坑——尼瑪,好難發現!
code     if(getArch().contain(“arm”)){//只在arm下載入System.loadLibrary(Bugly) ;System.loadLibrary(Bugly2);

}
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檔案