美文网首页
八、JNI-JNI补充功能

八、JNI-JNI补充功能

作者: MrDecoder | 来源:发表于2021-03-26 17:35 被阅读0次
  • JNI和线程
  • 注册本地方法

#1. JNI和线程

1.1 规约

当编写JNI函数时,有如下规约是必须要遵守的:

  1. JNIEnv是线程私有的,不能跨线程共享。
  2. Local references只在创建它的线程内有效,也不能跨线程共享。
1.2 Monitor Enter and Exit

JNI层也提供了类似Java层的线程同步操作,Java层多线程环境下为了解决多线程安全问题往往要通过锁机制对共享资源进行访问保护。

synchronized (obj) {
    ...  //sychronized block.
}

Java VM保证任何线程在执行同步block时会先获取obj Monitor,这样会确保任何时候只有最多一个线程能获取obj Monitor并且执行同步block。

Native层也有类似的方案去实现Java层的同步机制。

if (env->MonitorEnter(obj) != JNI_OK) {
    //Error handling.
}
//.... synchronized block.
if (env->MonitorExit(obj) != JNI_OK) {
    //Error handling.
}
MonitorEnter

进入obj Monitor,每一个Java对象都有它自己的Monitor。如果当前线程已经获取到Monitor,再次获取的时候会进行Monitor计数;如果线程尝试获取Monitor的时候,此时没有任何线程占有,那当前线程会变成Monitor owner。如果当前线程尝试获取Monitor时,Monitor已经被其他线程占有,那当前线程会阻塞住直到占有的线程释放Monitor再获取。

为了避免死锁,通过MonitorEnter获取Monitor的线程必须要通过MonitorExit释放所占有的Monitor。

jint MonitorEnter(JNIEnv *env, jobject obj);
MonitorExit

退出obj Monitor。尝试释放的线程必须是Monitor的所有者,通过MonitorExit线程会减少Monitor计数,直到为零时,当前的线程才会真正释放Monitor。

jint MonitorExit(JNIEnv *env, jobject obj);

#2. 注册本地方法

2.1 示例
CatchThrow.java
public class CatchThrow {
    static {
        System.loadLibrary("jnitest");
    }

    public native void nativeAccess() throws IllegalArgumentException;

    public native void dynamicRegister();

    private void callback() throws NullPointerException {
        throw new NullPointerException("CatchThrow.callback");
    }
}
CatchThrow.cpp
static JavaVM *g_cached_vm;
static jclass g_clazz;

void dynamicRegister(JNIEnv *env, jobject obj) {
    jmethodID mid;
    jthrowable throwable;

    mid = env->GetMethodID(g_clazz, "callback", "()V");
    if (mid == nullptr) {
        return;
    }
    env->CallVoidMethod(obj, mid);
    throwable = env->ExceptionOccurred();
    if (throwable) {
        jclass expClass;
        env->ExceptionDescribe();
        env->ExceptionClear();

        expClass = env->FindClass("java/lang/IllegalArgumentException");
        if (expClass == nullptr) {
            return;
        }
        env->ThrowNew(expClass, "Thrown from native code.");
    }
}

static JNINativeMethod gMethods[] = {
        {
                "dynamicRegister",
                "()V",
                (void *) dynamicRegister
        }
};

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    jclass clazz;

    g_cached_vm = vm;
    if (g_cached_vm == nullptr) {
        return JNI_ERR;
    }
    vm->GetEnv((void **) &env, JNI_VERSION_1_6);
    if (env == nullptr) {
        return JNI_ERR;
    }
    clazz = env->FindClass("com/nextlabs/hhu/myapplication/core/CatchThrow");
    if (clazz == nullptr) {
        return JNI_ERR;
    }
    g_clazz = (jclass) env->NewWeakGlobalRef(clazz);
    if (g_clazz == nullptr) {
        return JNI_ERR;
    }
    if (env->RegisterNatives(clazz, gMethods,
                             sizeof(gMethods) / sizeof(JNINativeMethod)) != JNI_OK) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    vm->GetEnv((void **) &env, JNI_VERSION_1_6);
    if (env == nullptr) {
        return;
    }
    env->DeleteWeakGlobalRef(g_clazz);
    g_clazz = nullptr;
}
2.2 Register API
RegisterNatives

注册clazz类中的native函数,参数methods表示待注册的method数组指针,参数nMethods表示待注册的native函数数量。

jint RegisterNatives(JNIEnv *env, jclass clazz,const JNINativeMethod *methods, jint nMethods);
JNINativeMethod
typedef struct { 
    char *name; 
    char *signature; 
    void *fnPtr; 
} JNINativeMethod; 
UnregisterNatives

取消注册clazz类中的native函数。

jint UnregisterNatives(JNIEnv *env, jclass clazz);

相关文章

  • 八、JNI-JNI补充功能

    JNI和线程 注册本地方法 #1. JNI和线程 1.1 规约 当编写JNI函数时,有如下规约是必须要遵守的: J...

  • 接口自动化2018-08-25

    前端页面的优化已经完成: 下一步计划,完善功能:1 补充sql功能2 补充其它几个页面的功能

  • redis其他补充功能

    redis除了基本的功能以后,还有许多功能有很大的用处。比如说慢查询分析、功能强大的Redis Shell、 Pi...

  • 八要素补充

    以上八要素,是取得修行成功的必要条件,缺一不可。修行者可以自我对照,如有缺项,要尽力弥补,否则因一条不备而前功尽弃...

  • 八、补充篇

    1.使用idea 新增一个javaclass文件模板: 尤其是接口测试代码,整的代码内容格式 等等 基本相同,只需...

  • 【PM知识框架六】产品技能- 功能设计

    一、功能设计产出物 1.1 产品功能列表 1.2 产品功能结构图 1.3 补充知识点 1.3.1 模块&功能&组件...

  • RocketMQ-Broker

    Broker在RocketMQ中承担着消息存储的功能。(待补充)

  • 2019-06-02

    今天在看高数自己补充项目一些功能

  • 文本编辑器与 Markdown

    方案一:Sublime + Typora 安装 package 来补充功能 MarkdownEditing:用于支...

  • day 40HTTP9网络协议说明

    课程介绍部分 课程知识回顾 ansible剧本角色功能配置说明 02.如何配置角色功能 补充: templates...

网友评论

      本文标题:八、JNI-JNI补充功能

      本文链接:https://www.haomeiwen.com/subject/xtqshltx.html