java.lang.UnsatisfiedLinkError: No implementation found for

时间:2023-01-21 15:42:22
E/AndroidRuntime: FATAL EXCEPTION: main
	Process: com.sgchip.pimr, PID: 20314
	java.lang.UnsatisfiedLinkError: No implementation found for int com.sgchip.pimr.util.IRDA.Init() (tried Java_com_sgchip_pimr_util_IRDA_Init and Java_com_sgchip_pimr_util_IRDA_Init__)

        使用第三方.so库调用JNI方法的时候出现了以上异常。

        看log说明是没有找到jni的方法,链接.so库错误。

        这个.so库是用来进行红外通讯的,是从另一个工程拷贝过来的。.so库里的接口都是带包名的,如果从别的项目拷贝过来,包名变了而.so库里的接口包名没变,就会造成找不到jni方法的异常。

        所以解决上述异常有两个方法,一个是改变.so库里接口的包名为新项目的包名,二是把.so库放在.so库接口对应的包名里。我采用的是第二种,问题解决。


        JNI的命名规则

        这里顺便说一下JNI的命名规则,对于传统的JNI编程来说,JNI方法跟Java类方法的名称之间有一定的对应关系,要遵循一定的命名规则,如下所示:

  1. 前缀: Java_
  2. 类的全限定名,用下划线进行分隔(_):com_oyp_jni_JniTest
  3. 方法名:getTestString
  4. JNI函数指定第一个参数: JNIEnv *
  5. JNI函数指定第二个参数: jobject
  6. 实际Java参数: jstring, jint ….

所以对于在Java类 com.oyp.jni.JniTest类的一个方法:

public native String getTestString (String oyp);

其对应的jni层的方法如下:

jstring Java_com_oyp_jni_JniTest_getTestString(JNIEnv * e, jobject clazz, jstring oyp);

如果不这样命名,当把动态库加载进DVM的时候,通过JNIEnv *指针去查找Java Native方法对应的JNI方法的时候,就会找不到了。 

注意,我们也可以利用函数注册的方法,将Java层的方法名跟JNI层的方法名的对应关系保存起来,注册到DVM中,就不需要这样的命名规范了。

        JNI 数据类型

我们知道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。

java.lang.UnsatisfiedLinkError: No implementation found for