JNI操作Java对象,JNI方法接收的第一个参数是JNIEnv*,第二个参数是Java对象jobject,我们可以在JNI中操作这个jobject进而操作Java对象提供的变量和方法,通常采用FindClass和GetObjectClass两个操作函数。
在C++中的函数原型为:
jclass FindClass(const char* name);//查找类信息
jclass GetObjectClass(jobject obj);//返回对象的类
在C中的函数原型为:
jclass (*FindClass)(JNIEnv* env, const char* name);
jclass (*GetObjectClass)(JNIEnv* env, jobject obj);
注意:FindClass中传入的name值为要查找类的全限定类名(以”/”分隔路径,
eg jclass clazz=env->FindClass(“android/util/Log”))。
上述表列出了JNI提供的操作域和方法的函数,在下述中将会用到。
下面是android/util/Log.java类的部分源码:
在android_util_Log.cpp中的register_android_util_Log方法中获取Log.java类的
VERBOSE,DEBUG等静态变量值如下
简单分析一下上述获取静态变量VERBOSE值2的过程。首先,通过FindClass找到android/util/Log的类信息clazz;然后以clazz为参数调用GetStaticFieldID(clazz,”VERBOSE”,”I”),其中VERBOSE是要访问的java域的名字,I是该Java域的类型签名,该函数返回了一个jfieldID代表Java成员变量;最后将该jfieldID传给GetStaticIntField得到Java层的成员变量VERBOSE的值2赋给levels.verbose。
接下来学习JNI函数是如何回调Java层方法的:
上述源码是java层,在java层中实现了一个callback()方法,该方法是由JNI层中的show方法调用。下述即为show方法在JNI层的实现:
通过上述可以得知在JNI层操作Java域和方法的步骤如下:
首先,通过调用FindClass或GetObjectClass函数获取jclass类信息clazz。
其次,调用对应的函数获取得到jfieldID或jmethodID。
最后,调用函数访问对应的Java域变量的值或调用Java方法。
注意,访问静态域和调用静态方法的JNI操作函数名中包含Static,反之就没有包含Static。