Android之JNI开发总结

Android Ndk开发常用网站收集,真正的高手并不是掌握所有的API而是需要的时候可以快速的找到要使用的API。

基础知识请移步:http://blog.csdn.net/xyang81/article/details/41777471

JNI动态加载: http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092491.html

JNI中C调用java的方法:http://www.cnblogs.com/xitang/p/4174619.html

JNI读取应用签名:https://www.pocketdigi.com/20141129/1398.html

NDK开发之日志打印:http://blog.csdn.net/u012702547/article/details/48222859

以上是学习和使用jni常用的几种方式,上述文章内容并不完全正确,稍加修改可正常使用,有需要的可以收藏下。 这篇文章主要介绍JNI开发中遇到的坑以及解决的方法。

一.静态注册和动态注册

为什么需要注册?其实就是给Java的native函数找到底层C,C++实现的函数指针。

  • 静态注册:

    通过包名类名一致来确认,Java有一个命令javah,专门生成某一个JAVA文件所有的native函数的头文件(h文件),步骤如下,我们只说Android项目下如何实施,其实理解了都一样

    静态方法注册JNI有哪些缺点?

1.必须遵循某些规则 2.名字过长 3,多个class需Javah多遍, 4.运行时去找效率不高

  • 动态注册 :

    在JNi层实现的,JAVA层不需要关心,因为在system.load时就会去掉JNI_OnLoad,有就注册,没就不注册。

  • 区别:

静态注册是用到时加载,动态注册一开始就加载好了,这个可以从DVM的源代码看出来。

二.C反射JAVA 的各种方法

TestClass类包一个构造方法、一个成员方法,一个静态方法,一个内部类,大多数的类都是由这三种方法组成的。下面要做的就是怎么在JNI调用这些方法。

查看方法签名

进入到classpath目录下: 命令: cd app/build/intermediates/classes/debug

查看外部类的签名 javap -s -p com.lb6905.jnidemo.TestClass

查看内部类的签名 javap -s -p com.lb6905.jnidemo.TestClass$InnerClass

结果如下:

在JNI中反射调用上述方法

此处需要注意 在C中: (*env)->方法名(env,参数列表) 在C++中: env->方法名(参数列表)

三.NewStringUTF函数请慎用

经常在使用 jstring (NewStringUTF)(JNIEnv, const char*);函数的过程中遇到如下错误 (1) .JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0x80

JNI调用newStringUTF时遇到不认识的字符串就直接出错退出~~,网上原因是dalvik/vm/CheckJni.c里面的checkUtfString函数检查通不过.

遇到问题时请排查以下几种问题

  • 1. 检查包名反射引用是否正确

  • 2. 检查方法签名,参数签名是否正确

  • 3. 将char 定义更换为const char

(2). JNI DETECTED ERROR IN APPLICATION: use of deleted weak global reference 0xb305f57b

string 对象和jstring对象从java传值或者新new 的字符串不能够直接引用,必须经过NewStringUTF进行转换,才可

四.推荐几种修改过的类型转换

(1)jstring转换为char*

(2)char * 转为jstring

(3)jstring 转为jbyte*

以上格式转换大家看到基本上都c反射java进行的格式转换,所以反射这块还是要多多了解的。

五. 内存管理

JNI内存管理请参考:https://www.ibm.com/developerworks/cn/java/j-lo-jnileak/ JNI 编程实现了 native code 和 Java 程序的交互,因此 JNI 代码编程既遵循 native code 编程语言的编程规则,同时也遵守 JNI 编程的文档规范。在内存管理方面,native code 编程语言本身的内存管理机制依然要遵循,同时也要考虑 JNI 编程的内存管理。

1、什么需要释放?

什么需要什么呢 ? JNI 基本数据类型是不需要释放的 , 如 jint , jlong , jchar 等等 。 我们需要释放是引用数据类型,当然也包括数组家族。如:jstring ,jobject ,jobjectArray,jintArray 等等。 当然,大家可能经常忽略掉的是 jclass ,jmethodID , 这些也是需要释放的哦

2、如何去释放?

1) 释放String

2) 释放 类 、对象、方法

3) 释放 数组家族

native method 调用 DeleteLocalRef() 释放某个 JNI Local Reference 时,首先通过指针 p 定位相应的 Local Reference 在 Local Ref 表中的位置,然后从 Local Ref 表中删除该 Local Reference,也就取消了对相应 Java 对象的引用(Ref count 减 1)。

end:以上就是开发中对jni的一些总结,有错误的地方请及时支出。本文仅供参考学习,转载请注明出处。谢谢

https://androidsummary.gitbook.io/androidsummary/

关注公众号:喘口仙氣 实时关注更新状态

Last updated

Was this helpful?