JNI 函数(六)系统级别的操作
(一) 注册方法
函数原型:jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethod);
根据 clazz 参数注册本地方法,methods 参数制定 JNINativeMethod 结构数组,该数组包含本地方法的名字、签名及函数指针。其中名字及签名是指向编码为 “UTF-8” 的指针;nMethod 参数表明数组中本地方法的个数。
这里说下 JNINativeMethod 这个结构体
1 typedef struct {
2 const char* name;
3 const char* signature;
4 void* fnPtr;
5 } JNINativeMethod;
参数:
env:JNI 接口指针
clazz:Java 类对象
methods:类中的 native 方法
nMethod:类中本地方法的个数
返回:
成功返回 0,失败返回负数
异常:
如果没有找到指定的方法或者方法不是本地方法,则抛出 NoSuchMethodError。
(二) 注销方法
函数原型:jint UnregisterNatives(JNIEnv *env, jclass clazz);
注销本地方法。类回收之前还没有被函数注册的状态。该函数一般不能在 Native 代码中被调用,它为特定的程序提供了一种重加载重链接本地库的方法。
参数:
JNI:接口指针
clazz:Java 类对象
返回:
注销成功返回 0,失败返回负数
(三) 监视操作
函数原型:jint MonitorEnter(JNIEnv *env, jobject obj);
obj 引用的底层 Java 对象关联的监视器。obj 引用不能为空。每个 Java 对象都有一个相关的监视器。如果当前线程已经有关联到 obj 的监视器,它将添加监视器的计数器来表示这个线程进入监视器的次数。如果关联至 obj 的监视器不属于任何线程,那当前线程将变成该监视器的拥有者,并设置计数器为 1,如果其他计数器已经拥有了这个监视器,当前线程将进行等待直到监视器被释放,然后再获得监视器的拥有权。
通过 MonitorEnter JNI 函数调用的监视器不能用 monitorexitJava 虚拟机指令或者同步方法退出。MonitorEnterJNI 函数调用和 monitorenter Java 虚拟机指令可能用同样的对象竞争地进入监视器。
为了避免死锁,通过 MoniterEnterJNI 函数调用进入的监视器必须用 MonitorExitJNI 调用退出,除非 DetachCurrentThread 接口被隐式的调用来释放 JNI 监视器
参数:
env:JNI 接口指针
obj:普通的 Java 对象或类对象
返回:
成功返回 0,失败返回负数
(四) 监视器退出
函数原型:jint MonitorExit(JNIEnv *env, jobject obj);
当前线程拥有与该 obj 关联的监视器,线程减少计数器的值来指示线程进入监视器的次数。如果计数器的值变为 0,则线程释放该监视器。Native 代码不能直接调用 MonitorExit 来释放监视器。而是应该通过同步方法来使用 Java 虚拟机指令来释放监视器
参数:
env:JNI接口指针
obj:普通的Java对象或类对象
返回:
成功返回0,失败返回负数
异常:
如果当前线程不拥有该监视器,则应该抛出 IllegalMonitorStateException