ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
### jni开发中的常见错误 #### 错误一 :java.lang.UnsatisfiedLinkError: Native method not found:(本地方法没有找到原因) - java.lang.UnsatisfiedLinkError: Native method not found: - 1. 本地函数名写错,如果本地方法名中有下划线“_”,则声明时,.c文件中在最后一个下划线后面加1,如以下代码所示 如果不加1会出现以下错误 ``` 07-20 23:00:15.542: E/AndroidRuntime(1307): Caused by: java.lang.UnsatisfiedLinkError: Native method not found: com.wsc.jnihelloworld.MainActivity.hello_FromC:()Ljava/lang/String; ``` ![](http://i.imgur.com/Q1w9GRH.png) 如果后面加1,如下图所示 MainActivity.class中修改如下 ![](http://i.imgur.com/H0oZAG5.png) hello.c中修改如下 ![](http://i.imgur.com/MXgicX1.png) 再重新编译生成.so文件,运行到模拟器上,正常运行 **虐心2** 如果遇到这种情况,方法名命名及其脑残如下图所示: ![](http://i.imgur.com/ee36h88.png) 这时,人工修改本地函数名,很麻烦,这时可以使用javah -jni命令,生成头文件 如果是jdk1.7版本则来到项目的src目录下运行javah命令,如果是jdk1.6版本,则到项目的bin目录下的class目录下运行javah命令 ![](http://i.imgur.com/Jpko7XP.png) 尽管报了GBK错误,但是那是编码格式的问题,不影响 本地方法声明在哪一个类中,就把这个类的全类名拿来,复制粘贴到DOS中 javah 后面,在项目文件鼠标移动到该处,按住F5刷新一下,就会出现头文件,打开可以看到 ![](http://i.imgur.com/rqImKmB.png) 打开头文件可以看到javah命令生成的头文件 ![](http://i.imgur.com/QsDSTJj.png) 这样就可以直接拿到本地函数名,不用人工修改本地函数名 - 2.忘记加载.so文件,没有调用System.loadlibrary() - System.loadlibrary()一般并不是调用它的时候才加载这个函数,可以在MainActivity中写一个静态代码块,MainActivity实例已创建,就加载.so文件 ####错误二 : findLibrary returned null #### - findLibrary returned null - 1.加载动态链接库时,动态链接库名字写错 System.loadLibrary("libhello");//动态链接库名字错了 报错如下 07-21 04:59:47.232: E/AndroidRuntime(1475): java.lang.UnsatisfiedLinkError: Couldn't load libhello from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.wsc.jnihelloworld-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.wsc.jnihelloworld-2, /system/lib]]]: findLibrary returned null - 2.平台类型错误,把只支持arm平台的.so文件部署到了x86CPU的设备上 报错如下 07-21 09:08:13.872: E/AndroidRuntime(1917): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load hello from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.wsc.jnihelloworld-1.apk,libraryPath=/data/app-lib/com.wsc.jnihelloworld-1]: findLibrary returned null Application.mk 中有这样一段话 By default, the NDK build system will generate machine code for the 'armeabi' ABI. This corresponds to an ARMv5TE based CPU with software floating point operations. You can use APP_ABI to select a different ABI. 默认情况下,NDK 生成系统将生成 'armeabi' ABI 的机器代码。这对应于 ARMv5TE 基于 CPU 浮点运算的软件。您可以使用 APP_ABI 来选择不同的 ABI。 没有指定APP_ABI,则它只去编译支持armeabi这种CPU的机器代码,想支持其他平台,就要添加APP_ABI指定想要支持的平台,支持多个平台时,用空格隔开,比如: APP_ABI := armeabi x86 **注意:genymotion模拟器应该都是支持x86CPU平台,所以APP安装到这些模拟器,应该注意指定APP_ABI** 重新ndk-build生成x86平台下的.so文件如图,然后运行到x86模拟器 ![](http://i.imgur.com/BRSSsFj.png) ### cpu平台 ### * arm :指令集,精简指令集,简单的事情,效率特别高, * 优点:移动平台,执行简单的指令操作,效率高,资源消耗低,功耗低。 * 缺点:复杂逻辑的时候,就有缺陷。 * 发展:arm平台的服务器 * x86:复杂指令集,SSE,SSE3 * 优点:执行复杂业务逻辑的时候,性能非常强大,这种性能远超arm平台 * 缺点:耗电,功耗高。 * 发展:x86 平台手机cpu,x86:联想的k900,拉拢一些山寨厂商使用x86 cpu * mips:cpu 类型 * 龙芯:用mips * sigma:机顶盒 ### javah ### - jdk 1.7项目 src目录下运行 javah - jdk 1.6项目 bin目录下classes文件夹 - javah native方法声明的java类的全类名 从上图可以看到在ndk-build时,出现一个warning,说APP_PLATFORM ,Android-19比最小版本14大,解决这个warning可以在Application.mk中添加 APP_PLATFORM := android-14 ![](http://i.imgur.com/eder0Dh.png) 可以看到,不再报这个warning ####错误三: 使用javah生成头文件报找不到类文件 #### 很有可能是由你的JDK环境变量配置出错,记住CLASSPATH这个系统变量,前面应该加上“.;”,如图所示 ![](http://i.imgur.com/X3oPrFk.png)