目录
一、JNI动态注册是什么?
二、JNI动态注册使用步骤
1.新增gMethods数组和JNI_OnLoad函数
2.完整HelloWorld.cpp
3.运行测试
总结
静态注册的情况下,java调用的接口和jni层实现的接口有强制的一一对应关系,jni层的接口名必须是java_包名_函数名,但是动态注册情况下,jni的函数名可以自定义,然后通过数组数定义java函数名和jni函数名的对应关系。
//函数名从Java_HelloWorld_sayhello改为Dynamic_Java_HelloWorld_sayhello
JNIEXPORT void JNICALL Dynamic_Java_HelloWorld_sayhello
(JNIEnv *, jobject)
{
printf("cpp say hello world\n");
}
//gMethods定义了java接口和jni接口的对应关系
static JNINativeMethod gMethods[]=
{
{"sayhello","()V",(void*)Dynamic_Java_HelloWorld_sayhello}
};
//JNI_OnLoad会在java层动态加载库System.loadLibrary()的时候调用
jint JNI_OnLoad(JavaVM* vm,void* reserved)
{
JNIEnv *env=NULL;
jint result =-1;
if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK)
{
return -1;
}
//通过反射机制找到HelloWorld类
char className[20]={"HelloWorld"};
jclass clazz=env->FindClass((const char*)className);
//为HelloWorld类定义jni函数调用关系
if(env->RegisterNatives(clazz,gMethods,1)<0)
{
return -1;
}
//默认JNI_VERSION_1_1是不支持JNI_OnLoad的,所以要返回JNI_VERSION_1_4
result=JNI_VERSION_1_4;
printf("JNI_ONload\n");
return result;
}
#include
#include
#include "HelloWorld.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: sayhello
* Signature: ()V
*/
JNIEXPORT void JNICALL Dynamic_Java_HelloWorld_sayhello
(JNIEnv *, jobject)
{
printf("cpp say hello world\n");
}
static JNINativeMethod gMethods[]=
{
{"sayhello","()V",(void*)Dynamic_Java_HelloWorld_sayhello}
};
jint JNI_OnLoad(JavaVM* vm,void* reserved)
{
JNIEnv *env=NULL;
jint result =-1;
if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK)
{
return -1;
}
char className[20]={"HelloWorld"};
jclass clazz=env->FindClass((const char*)className);
if(env->RegisterNatives(clazz,gMethods,1)<0)
{
return -1;
}
result=JNI_VERSION_1_4;
printf("JNI_ONload\n");
return result;
}
#ifdef __cplusplus
}
#endif
#编译
gcc HelloWorld.cpp --shared -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC
#运行
java HelloWorld
#输出:
#JNI_ONload
#cpp say hello world
#call jni sayhello
动态注册可以自由的定义jni接口。