无论静态注册或是动态注册、都需要在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 descriptor | Java type | |
---|---|---|
Z | boolean | |
B | byte | |
C | char | |
S | short | |
I | int | |
J | long | |
F | float | |
D | double | |
V | void |
对象类型为 L 开头 + ; 结尾
如字符类型
LJava/lang/String;
数组为 [ 开头 + 描述符
int[] => [I
float[] => [F