NDK开发之动态注册本地方法

2019-05-16  本文已影响0人  呵呵_9e25
  1. 静态注册
    一般我们写的java native方法在c层都有对应的方法,例如
    java 代码如下
package com.example.administrator.ndkstudydemo.demo;
public class CounterNative {
 private native void init();
}

声明了一个init本地方法,对应的如果静态注册,会生成一个这样的方法在c代码里面,c代码如下

extern "C"
JNIEXPORT void JNICALL
Java_com_example_administrator_ndkstudydemo_demo_CounterNative_init(JNIEnv *env,jobject thiz) {}

这就是典型的静态注册,通过Java_包名_方法名的规则生成

正常情况下它没什么问题,但是它第一相对不安全,为啥这么说?

相对不安全
  1. 动态注册
    首先java代码不变,我们改变c++代码
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    jvm = vm;
    if (jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
   //动态注册函数
    if (registerNatives(env) != JNI_TRUE) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

首先重写JNI_OnLoad方法,核心逻辑是注释部分代码if (registerNatives(env) != JNI_TRUE) { return -1; },接下来我们看一下这个registerNatives函数实现

//java类全路径
static const char *classPathName = "com/example/administrator/ndkstudydemo/demo/CounterNative";
//方法数组
static JNINativeMethod methods[] = {
        {"init", "()V", (void *) Java_com_example_administrator_ndkstudydemo_demo_CounterNative_nativeSetup}
};
static int registerNatives(JNIEnv *env) {
    registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0]));
    return JNI_TRUE;
}

static int registerNativeMethods(JNIEnv *env, const char *className,
                                 JNINativeMethod *gMethods, int numMethods) {
    jclass clazz = env->FindClass(className);
   //调用env注册本地方法的函数,传入需要修改的方法数组,和需要修改的方法数
    env->RegisterNatives(clazz, gMethods, numMethods);
    return JNI_TRUE;
}

其实就是调用env的一个注册本地方法的函数env->RegisterNatives(clazz, gMethods, numMethods),它需要三个参数,第一个是方法所在的class对象,还有对应的java方法数组,第三个参数就是方法数组数目,这样就完成了动态注册本地方法

  1. 总结
    java的本地方法名init只是本地方法nativeSetup的一个别名,在vm方法表里存储了他们的对应关系,才使得java方法能正确访问到本地方法
上一篇下一篇

猜你喜欢

热点阅读