JNI使用小结

本文详细介绍了JNI的动态注册过程,包括JNI函数签名的定义和使用,以及Java到JNI的数据类型转换规则。在JNI中,基本类型转换简单,引用类型统一用jobject表示。JNIEnv提供了调用Java函数和操作对象的方法,如Call<>Method和GetFieldID。文章还探讨了Local Reference、Global Reference和Weak Global Reference的垃圾回收机制,以及如何创建和使用全局引用。此外,讨论了调用超类方法和FindClass与GetObjectClass的区别。
摘要由CSDN通过智能技术生成

以下内容主要参考深入理解Android卷1.

JNI函数动态注册:

使用这个数据结构存储一个JNI函数的注册信息:

typedef struct {

   //Java中native函数的名字,不用携带包的路径。例如“native_init“。

constchar* name;    

//Java函数的签名信息,用字符串表示,是参数类型和返回值类型的组合。

    const char* signature;

   void*       fnPtr;  //JNI层对应函数的函数指针,注意它是void*类型。

} JNINativeMethod;

从以上成员看出java中声明的native函数好像可以对应上该jni文件中的函数,但是实际上jni函数的在这个结构上是唯一的,但是java声明的不是,因为不带包路径,只是一个函数名,怎么知道这个函数是哪个类的呢,如果其他java文件也有这样一个同名的native声明呢?其实在注册时,会去获取对应的java类对象(Class类型的对象)。

为JNI动态库中的所有JNI函数建立一个JNINativeMethod数组,注册就用这个数组作为参数。示例:

static JNINativeMethod g_methods[] = {
    {"nativeSetBlueLightFilterStrength", "(I)Z", (void*)nativeSetBlueLightFilterStrength},
    {"nativeGetBlueLightFilterStrength", "()I", (void*)nativeGetBlueLightFilterStrength},
    {"nativeEnableBlueLightFilter", "(Z)Z", (void*)nativeEnableBlueLightFilter},
    {"nativeIsBlueLightFilterEnabled", "()Z", (void*)nativeIsBlueLightFilterEnabled},
    {"nativeGetBlueLightFilterStrengthRange", "()I", (void*)nativeGetBlueLightFilterStrengthRange},
    {"nativeBlueLightFilterInit", "()Z", (void*)nativeBlueLightFilterInit},
};

JNI函数签名:

JNI规范定义的函数签名信息格式:

(参数1类型标示参数2类型标示...参数n类型标示)返回值类型标示

比较繁琐,具体编码时,读者可以定义字符串宏

类型标示示意表

类型标示

Java类型

类型标示

Java类型

Z

boolean

F

float

B

byte

D

double

C

char

Ljava/lang/String;

String

S

short

[I

int[]

I

int

[Lava/lang/object;

Object[]

J

long

上面列出了一些常用的类型标示,如果Java类型是数组,则标示中会有一个“[”,另外,引用类型(除基本类型的数组外)的标示最后都有一个“;”,返回值签名时也是要加分号的

 函数签名小例子

函数签名

Java函数

“()Ljava/lang/String;”

String f()

“(ILjava/lang/Class;)J”

long f(int i, Class c)

“([B)V”

void f(byte[] bytes)

当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad的函数,如果有,就调用它,而动态注册的工作就是在这里完成的。
 

在JNI_OnLoad函数中注册会用到一下两行代码:

/*

env指向一个JNIEnv结构体,classname为对应的Java类名(全路径名,包名+类名),由于

JNINativeMethod中使用的函数名并非全路径名,所以要指明是哪个类。

*/

jclass clazz =  (*env)->FindClass(env, className);

//调用JNIEnv的RegisterNatives函数,注册关联关系。

(*env)->RegisterNatives(env, clazz, gMethods,numMethods);

示例:

/*
 * Register several native methods for one class.
 */
static int registerNativeMethods(JNIEnv* env, const char* className,
    JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值