JNI可以说是Java 和Native 的桥梁 起承上启下的作用,没有JNI Android就只能访问到Java 的Framework层,在想深入可谓是举步维艰.
静态注册就是根据函数名来建立Java函数与JNI函数一一对应的关系
JNI函数名的规则:Java_包名_类名_函数名,也就是以这种规则来确认JNI函数与某个类Java函数的对应关系
在Java加载so库的时候会吧JNI的方法链接过来,无论你用还是不用,此方法都已经存在比较浪费内存
方便,快捷,省心,不易出错,
不能轻易修改包名,JNI函数名过长,不灵活
动态注册是在JNI里面存在一张JNI函数与Java函数的映射表,然后把这张表丢给JavaVM,JavaVM就可以通过这张表去寻找JNI函数,而不是通过函数名的规则去遍历JNI函数,动态注册的效率更高,更清晰可控.
在java引用的cpp库文件里会存在一个JNI_OnLoad函数,这个函数就像Java的构造函数一样,如果不重写,JNI会默认存在.
在Java 代码中通过加载库文件,就会加载JNI_OnLoad()方法,若不重写则会默认存在
JNINativeMethod 结构体 这个结构体基本上都是以数组的形式进行使用
typedef struct {
const char* name; // Java函数名
const char* signature; //Java函数签名
void* fnPtr; //JNI函数指针
} JNINativeMethod;
RegisterNatives 注册JNI与Java对应关系
//返回int类型 0代表成功
jint RegisterNatives(jclass clazz,//注册那个Java类的native函数
const JNINativeMethod* methods, //上面的结构体
jint nMethods //注册多少个函数
)
{
return functions->RegisterNatives(this, clazz, methods, nMethods); }
在native-lib.cpp文件中重写JNI_OnLoad()方法
JNIEXPORT jint JNI_OnLoad(JavaVM *javaVm, void *) {}
//JNI函数
jstring dynamicMethod(JNIEnv *env, jobject thiz, jstring str) {
}
//+++++++++++++++++++++++++++++++++++++++++++++++[动态注册代码]
JavaVM *javaVm; //全局的JavaVM
const char *mainActivityName = "com/json/new_jni_pproject_11_1/MainActivity"; //注册的Java类包名
//Java函数名与JNI函数名对应关系
const JNINativeMethod jniNativeMethod[] =
{
{
"dynamicMethod", "(Ljava/lang/String;)Ljava/lang/String;", (jstring *) (dynamicMethod)}
};
JNIEXPORT jint JNI_OnLoad(JavaVM *javaVm, void *) {
::javaVm = javaVm; //:: 表示域 与this类似
JNIEnv *env = nullptr;
javaVm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);//实例化JNIEnv
jclass mainActivityClass = env->FindClass(mainActivityName);
//进行注册
jint result= env->RegisterNatives(mainActivityClass, jniNativeMethod,
sizeof(jniNativeMethod) / sizeof(JNINativeMethod));
if(result!=JNI_OK)
{
LOGI("动态函数 初始化失败");
}
LOGI("动态函数 初始化完成");
return JNI_VERSION_1_6;
}