天天看點

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型

今天使用第三方的so庫時候,調用JNI方法時出現了錯誤。報錯如下所示:

在MainActivity中,嘗試調用NeteaseMusicUtils類封裝好的JNI方法,代碼如下所示:

而com.netease.xtc.cloudmusic.utils.NeteaseMusicUtils代碼如下:

其中so庫位置如下所示:

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型

再一次檢視下錯誤日志,如下所示:

錯誤日志提示我們沒有 Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit 方法的實作,如下所示:

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型

然後我去咨詢了一下第三方提供so庫的從業人員,回複說NeteaseMusicUtils類的包名一定要是com.netease.cloudmusic.utils。原因是JNI接口Java_com_netease_xtc_cloudmusic_utils_NeteaseMusicUtils_nativeInit中,com.netease.xtc.cloudmusic.utils代表的是package name,NeteaseMusicUtils則是class name。

而第三方提供so庫的從業人員的c檔案的定義JNI接口為Java_com_netease_cloudmusic_utils_NeteaseMusicUtils_nativeInit,即:package name必須為:com.netease.cloudmusic.utils,而class name必須為 NeteaseMusicUtils。

也就是說,我們.so中函數聲明涉及到的package name和class name與調用它的package name和class name不符。是以我們要改變我們工程中的package name和class name。使其與.so檔案中函數簽名提示的一緻,在這個類中加入native方法的聲明。

好吧,我建立一個包名為com.netease.cloudmusic.utils,并把NeteaseMusicUtils類移到該包名地下。

未移動NeteaseMusicUtils到com.netease.cloudmusic.utils包之前

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型

移動NeteaseMusicUtils到com.netease.cloudmusic.utils包之後

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型

然後重新編譯,成功運作。

這裡順便說一下JNI的命名規則,對于傳統的JNI程式設計來說,JNI方法跟Java類方法的名稱之間有一定的對應關系,要遵循一定的命名規則,如下所示:

字首: Java_

類的全限定名,用下劃線進行分隔(_):com_oyp_jni_JniTest

方法名:getTestString

JNI函數指定第一個參數: JNIEnv *

JNI函數指定第二個參數: jobject

實際Java參數: jstring, jint ….

是以對于在Java類 com.oyp.jni.JniTest類的一個方法:

其對應的jni層的方法如下:

如果不這樣命名,當把動态庫加載進DVM的時候,通過JNIEnv *指針去查找Java Native方法對應的JNI方法的時候,就會找不到了。

注意,我們也可以利用函數注冊的方法,将Java層的方法名跟JNI層的方法名的對應關系儲存起來,注冊到DVM中,就不需要這樣的命名規範了。

我們知道Java的資料類型是跟C/C++的資料類型是不一樣的,而JNI是處于Java和Native本地庫(大部分是用C/C++寫的)中間的一層,JNI對于兩種不同的資料類型之間必須做一種轉換,是以在JNI跟Java之間就會有資料類型的對應關系。 在JNI中,提供了以下各種資料類型,可以分為原生類型和引用類型: 對于原生類型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其與java端的資料類型對應如下表:

java

jni

char

jchar

byte

jbyte

short

jshort

int

jint

long

jlong

float

jfloat

double

jdouble

boolean

jboolean

對于引用類型則有:jobject, jstring, jthrowable, jclass, jarray, 以及繼承于jarray,對應于其原生類型的8種jarray和jobjectarray。

【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型
作者:歐陽鵬 歡迎轉載,與人分享是進步的源泉!
【我的Android進階之旅】Android調用JNI出錯 java.lang.UnsatisfiedLinkError: No implementation found for的解決方法錯誤描述錯誤分析錯誤解決方法JNI的命名規則JNI 資料類型