JNI 学习笔记——通过RegisterNatives注册原生方法

1.概述

在上一次的笔记《JNI学习笔记》 中介绍了Native程序与Java程序的互相调用。其中Java调用Nativie方法通常的步骤是:

    1. 声明native方法: private native void sayHello();
    1. 通过javah 生成native程序的头文件HelloJNI.h
    1. 实现对应的navtive方法
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {
   printf("Hello World!\n");
   return;
}

这种方法每次增加方法时, native方法名称都需要带上长长的一坨JNIEXPORT void JNICALL Java_HelloJNI_, 包名很长的话更是不能忍。除此之外对于Native方法的方法名也不能修改。

如果你想摆脱这种冗长的规则, 不妨尝试在JNI的JNI_OnLoad()方法中通过RegisterNatives注册Java需要调用的Native方法。

2. JavaVM 和 JNIEnv

注册navtive方法之前我们需要了解JavaVM, JNIEnv:

JavaVMJNIEnv 是JNI提供的结构体.

JavaVM 提供了允许你创建和销毁JavaVM的"invokation interface"。理论上在每个进程中你可以穿件多个JavaVM, 但是Android只允许创造一个。

JNIEnv 提供了大部分JNI中的方法。在你的Native方法中的第一个参数就是JNIEnv.

JNIEnv 用于线程内部存储。 因此, 不能多个线程共享一个JNIEnv. 在一段代码中如果无法获取JNIEnv, 你可以通过共享JavaVM并调用GetEnv()方法获取。

3. JNI_OnLoad()方法

当Java层代码中执行:

System.loadLibrary("NativeLib"); //NativeLib 为native模块名称

Native 中的 JNI_OnLoad(JavaVM *vm, void *reserved) 方法会被调用。此时可以注册对应于Java层调用的navtive方法。

4. JNINativeMethod结构体

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

以上代码为jni.h中的源码, 可见JNINativeMethod包含三个元素: 方法名, 方法签名, native函数指针。

该结构体用于描述需要注册的方法信息。

5. RegisterNatives方法

jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
        jint nMethods)

该方法是JNI环境提供的用于注册Native方法的方法。

6. 完整实现

6.1. Java代码实现

Java层代码不需要做任何调整

public class NativeLib {

    public static native String getNativeString();

    static {
        System.loadLibrary("NativeLib");
    }
    

6.2. C++ 代码实现

6.2.1 实现Native方法

//可以随意定义方法名
jstring getString() 
{
    JNIEnv *env = NULL;
    g_jvm->AttachCurrentThread(&env, NULL); //g_jvm为JavaVM指针
    
    return env->NewStringUTF("This is Natvie String!");
}

6.2.2 定义JNINativeMethod数组, 声明需要注册的方法

static JNINativeMethod methods[] = {
        {"getNativeString", "()Ljava/lang/String;", reinterpret_cast<void*>(getString)}
};

其中getNativeString为Java类中定义的Native方法名。

()Ljava/lang/String; 为方法的签名, ()表示该方法无参数, Ljava/lang/String;表示返回值为Java中的String类型。具体签名规则请参考《JNI学习笔记》 中的内容。

reinterpret_cast<void*>(getString) 为Native实现的方法名。这里强制转换成了函数指针。

6.2.3 JNI_OnLoad()方法实现

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    JNIEnv* env;
    if (JNI_OK != vm->GetEnv(reinterpret_cast<void**> (&env),JNI_VERSION_1_4)) {
        LOGW("JNI_OnLoad could not get JNI env");
        return JNI_ERR;
    }

    g_jvm = vm; //用于后面获取JNIEnv
    jclass clazz = env->FindClass("com/example/myndkproj/NativeLib");  //获取Java NativeLib类

    //注册Native方法
    if (env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof((methods)[0])) < 0) {
        LOGW("RegisterNatives error");
        return JNI_ERR;
    }

    return JNI_VERSION_1_4;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容