动态注册 JNI

传统的 JNI 注册是动态注册

package wills.jniDemo

public class Utils{
    static{
      System.loadLibrary("native-lib");
    }

    public native String stringFromJNI();
}

//native-lib.cpp
JNIEXPORT 
jstring JNICALL Java_wills_jniDemo_Utils_stringFromJNI(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

这种静态注册需要将 native 方法按照 JNI 的格式进行编写。

下面介绍动态注册 JNI,譬如想把这个stringFromJNI 在 native 方法名定义为sayHello()

package wills.jniDemo

public class Utils{
    static{
      System.loadLibrary("native-lib");
    }

    public native String stringFromJNI();
}

//native-lib.cpp
//编写想要和 Java层方法绑定的方法,参数要一致
jstring sayHello(JNIEnv *env, jobject obj) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

//要动态注册 JNI 方法的那个类
static const char *jniClassName = "wills/jniDemo/Utils";
//将 Java 方法和 native 方法绑定
//"Java 层的方法层","方法签名","对应的 native 层的方法指针"
static JNINativeMethod methods[] = {
        {"stringFromJNI", "()Ljava/lang/String;", (void *) jniSayHello},
};

static int registerNatives(JNIEnv *env) {
    jclass clazz = env->FindClass(jniClassName);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    jint methodSize = sizeof(methods) / sizeof(methods[0]);
    //RegisterNatives 注册,"注册的类","注册的方法[]","注册的方法数"
    if (env->RegisterNatives(clazz, methods, methodSize) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

//在加载这个 library 后自动调用的方法
JNIEXPORT jint  JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    if (!registerNatives(env)) {
        return JNI_ERR;
    }
    result = JNI_VERSION_1_6;
    return result;
}

这样就可以不用编写符合 JNI 规范的方法名了,据说还能提高 native 方法的寻找速度。如果 native 方法比较多,这样编写也比较方便。

关于方法签名可以根据网上资料自己写,或者用

javap -s -p xxx.class

用来获取签名

你可能感兴趣的:(动态注册 JNI)