Android JNI 详解

JNI的作用

全称是 Java Native Interface (Java本地接口),JNI来自于Java,Android作为一种嵌入式的操作系统,有大量的驱动、硬件相关的功能必须在native层实现,其次C/C++代码的效率也是优于Java的代码,所以一些耗时的计算操作,例如一些加密算法还是应该用JNI开发。
在JNI中 无论是Java到C/C++还是C/C++到Java,中间都没有跨线程的调用,但是在各自的打印线程Id时会得到不同的线程Id,这是因为Java中的线程Id是一个从1开始的整数,而C/C++中则是一个与线程相关的数据结构的指针值。

JNI的用法

  • 装在JNI动态库
    使用JNI时,C/C++的代码是存放在动态库中的,我们需要将动态库加载到进程的内存空间中 装在库是放在System类中的LoadLibrary()方法,原型如下:
public static void loadLibary(String libName)

动态库名称是以lib开头 以.so结尾(在Windows中是.dll) JNI是源于Java中产物,Java为了做到系统之间的兼容,所以将lib 和后缀名省去,譬如说 libmyjni.so 最终传递给loadLibary的参数是myjni

  • 定义native代码
    在Java中使用JNI方法需要在方法前加上native关键字
private static native void init()
  • 编写JNI动态库
    JNI动态库中有一个方法叫做 “JNI_OnLoader”的函数,这个函数会在动态库被加载后由系统调用,用于完成JNI函数的注册,这样做的目的是使得Java中的native方法能够找到JNI动态库中的对应的C的函数。

  • 参数签名
    参数的签名的作用是代表数据类型,在Java中的数据类型与JNI中都有相应的表示方法

参数签名Java类型JNI类型
Zbooleanjboolean
Ccharjchar
Bbytejbyte
Sshortjshort
Iintjint
Jlongjlong
Ffloatjboolean
Ddoublejdouble
[Zboolean[]jbooleanArray
[Cchar[]jcharArray
[Bbyte[]jbyteArray
[Sshort[]jshortArray
[Iint[]jintArray
[Jlong[]jlongArray
[Ffloat[]jbooleanArray
[Ddouble[]jdoubleArray

注:复杂类型的签名格式 ‘L’加上“全限定类名” 再加上“; ” 例如Java中的String 的参数签名应该是
L/java/lang/String;
注:有关数组相关的操作
JNI中的数组类型 例如jbyteArray、jcharArray其实只是jobject通过typedef定义出来的别名。在JNIEnv中也定义了与数组相关的操作函数
- 获取数组元素的个数
jsize GetArrayLength(jarray array)
- 将JNI数组类型转换为基本数组类型(每种基本类型都有自己的转换)
jint* GetIntArrayElements(jintArray array, jint* elems, Jint mode)
- 回收数组的内存
void ReleaseIntArrayElements(jintArray array, jint * elems, jint mode)
注:有关字符串的相关操作
- 获取字符串的长度
jsize GetStringUTFLength(jstring string)
- 转换成UTF-8
const char* GetStringUTFChars(jstring string, jboolean* iscopy)
- 转换成Unicode的字符串
const jchar* GetStringChars(jstring string, jboolean* iscopy)

在C/C++ 中调用Java

  • 创建一个Java对象
jobject NewObject(jclass clazz, jmethodID methodID, ...)

参数claszz是指Java对象(不是类的实例对象),可以通过函数FindClass()获得;
参数methodID 是构造函数
FindClass()的原型是:

jclass FindClass(const* char)

例如String类的传入参数就是 “/java/lang/String”
在调用一个Java对象的方法或对Java中的域变量进行操作时,首先需要获取这个方法或者变量Id。可以用以下方法获取:

jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)

注: 如果是获得构造函数在name 的传入参数必须是 “ < init > ”

jfield GetFieldID(jclass clazz, const char* name, const char* sig)
  • 调用Java类的方法
    JNI环境JNIENv提供了多种调用Java类中的方法
    JNI提供了针对不同返回值的函数:
jchar CallCharMethod(jobject object, jmethodID methodID, ...)
jboolean CallBooleanMethod(jobject object, jmethodID methodID, ...)
jint CallIntMethod(jobject object, jmethodID methodID, ...)
jbyte CallByteMethod(jobject object, jmethodID methodID, ...)
jshort CallShortMethod(jobject object, jmethodID methodID, ...)
jlong CallLongMethod(jobject object, jmethodID methodID, ...)
jdouble CallDoubleMethod(jobject object, jmethodID methodID, ...)
jobject CallObjectMethod(jobject object, jmethodID methodID, ...)
void CallVoidMethod(jobject object, jmethodID methodID, ...)

如果是调用的静态方法只需要Java类中的对象就可以了不需要实例对象,并且在每条函数前面多了一个static 字样:

jchar CallStaticCharMethod(jobject object, jmethodID methodID, ...)
jboolean CallStaticBooleanMethod(jobject object, jmethodID methodID, ...)
jint CallStaticIntMethod(jobject object, jmethodID methodID, ...)
jbyte CallStaticByteMethod(jobject object, jmethodID methodID, ...)
jshort CallStaticShortMethod(jobject object, jmethodID methodID, ...)
jlong CallStaticLongMethod(jobject object, jmethodID methodID, ...)
jdouble CallStaticDoubleMethod(jobject object, jmethodID methodID, ...)
jobject CallStaticObjectMethod(jobject object, jmethodID methodID, ...)
void CallStaticVoidMethod(jobject object, jmethodID methodID, ...)
  • 存取Java类的域变量
    JNIEnv定义了一组函数 可以对Java对象中的域变量进行存取,根据基本类型的不同以及静态与非静态的不同,对应有不同的函数:

获取非静态变量对应的一系列函数

jobject GetObjectField(jobject obj, jfieldID fieldID)
jboolean GetBooleanField(jobject obj, jfieldID fieldID)
jbyted GetByteField(jobject obj, jfieldID fieldID)
jchar GetCharField(jobject obj, jfieldID fieldID)
jshort GetShortField(jobject obj, jfieldID fieldID)
jint GetIntField(jobject obj, jfieldID fieldID)
jlong GetLongField(jobject obj, jfieldID fieldID)
jfloat GetFloatField(jobject obj, jfieldID fieldID)
jdouble GetDoubleField(jobject obj, jfieldID fieldID)

获取静态变量对应的一系列函数

jobject GetStaticObjectField(jobject obj, jfieldID fieldID)
jboolean GetStaticBooleanField(jobject obj, jfieldID fieldID)
jbyted GetStaticByteField(jobject obj, jfieldID fieldID)
jchar GetStaticCharField(jobject obj, jfieldID fieldID)
jshort GetStaticShortField(jobject obj, jfieldID fieldID)
jint GetStaticIntField(jobject obj, jfieldID fieldID)
jlong GetStaticLongField(jobject obj, jfieldID fieldID)
jfloat GetStaticFloatField(jobject obj, jfieldID fieldID)
jdouble GetStaticDoubleField(jobject obj, jfieldID fieldID)

设置非静态成员变量

void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
void SetBooleantField(jobject obj, jfieldID fieldID, jboolean value)
void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
void SetCharField(jobject obj, jfieldID fieldID, jchar value)
void SetShortField(jobject obj, jfieldID fieldID, jshort value)
void SetIntField(jobject obj, jfieldID fieldID, jint value)
void SetLongField(jobject obj, jfieldID fieldID, jlong value)
void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)

设置静态成员变量

void SetStaticObjectField(jobject obj, jfieldID fieldID, jobject value)
void SetStaticBooleantField(jobject obj, jfieldID fieldID, jboolean value)
void SetStaticByteField(jobject obj, jfieldID fieldID, jbyte value)
void SetStaticCharField(jobject obj, jfieldID fieldID, jchar value)
void SetStaticShortField(jobject obj, jfieldID fieldID, jshort value)
void SetStaticIntField(jobject obj, jfieldID fieldID, jint value)
void SetStaticLongField(jobject obj, jfieldID fieldID, jlong value)
void SetStaticFloatField(jobject obj, jfieldID fieldID, jfloat value)
void SetStaticDoubleField(jobject obj, jfieldID fieldID, jdouble value)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值