JNI - 动态注册函数

99 阅读1分钟

无论静态注册或是动态注册、都需要在Java中声明native方法

public native int getAge(int input);

静态注册方法需要按照JNI规定命名

固定前缀 + 返回值 + 关键字

extern "C" JNIEXPORT jstring JNICALL

Java_packagename_classname_getAge( JNIEnv* env,jobject) {}

动态注册无需按照JNI规定进行命名

动态注册需要重写 JNI_OnLoad方法

jint JNI_OnLoad(JavaVM* vm,void* reserved){

    JNIEnv* env = NULL;

    JNINativeMethod mtables[] = {

        {"getAge","(I)I",(void *)getAge}

    };

    jint result = -1;

    if(vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK){

        return result;

    }

    jclass cls;

    cls = env->FindClass("Person");

    if(cls == NULL){

        return result;

    }

    if(env->RegisterNatives(cls, mtables,1) < 0){

        return result;

    }

    env->DeleteLocalRef(cls);

    return JNI_VERSION_1_4;

}

JNI_OnLoad方法等定义都在 jni.h 头文件中。

动态注册第一步:通过Java虚拟机获取到 jni 运行环境变量

vm->GetEnv((void **) &env, JNI_VERSION_1_4)

需要传入一个任意类型指针的指针变量, 这里为 JNIEnv 指针类型 JNIEnv* env 以及 JNI的版本(对应jvm版本)

拿到env后根据类名获取到 jclass 对象,再使用jclass对象来注册方法

描述符表格

field descriptorJava type
Zboolean
Bbyte
Cchar
Sshort
Iint
Jlong
Ffloat
Ddouble
Vvoid

对象类型为 L 开头 + ; 结尾

如字符类型

LJava/lang/String;

数组为 [ 开头 + 描述符

int[] => [I

float[] => [F