**
一、JNI函数注册方法以及时机图解
**
二、介绍
- 什么是 JNI 函数注册:
当 Java 虚拟机调用 native 方法时,需要调用对应的 JNI 函数,而 JNI 函数注册讨论的就是如何确定 natvie 方法与 JNI 函数之间的映射关系。
2.JNI函数注册的方式:
1)静态注册
2)动态注册
3.JNI函数注册方式的优缺点:
1)静态注册:
静态注册的优点是简单,因为静态注册采用的是基于约定的命名规则,所以可以通过 javah 或 IDE 自动生成函数声明。缺点是修改 Java 类名或方法名时,需要同步修改 JNI 函数命名。
2)动态注册:
动态注册的优点是灵活,因为动态注册可以自由定义 Java 方法和 JNI 函数命名的映射,当 Java 类名或方法名时只需要修改映射关系即可。缺点是牺牲了静态注册基于约定带来的便捷性。
三、具体实现
1、静态注册:
静态注册采用的是基于「约定」的命名规则,通过 javah 可以自动生成 native 方法对应的函数声明。例如:
HelloWorld.java
package com.xurui.hellojni;
public class HelloWorld {
public native void sayHi();
}
com_xurui_hellojni_HelloWorld.h
...
JNIEXPORT void JNICALL Java_com_xurui_hellojni_HelloWorld_sayHi
(JNIEnv *, jobject);
...
2)命名规则
静态注册的命名规则分为「无重载」和「有重载」两种情况:无重载时采用「短名称」规则,有重载时采用「长名称」规则。
短名称规则(short name)
1、前缀 Java_;
2、类的全限定名(带下划线分隔符_);
3、方法名
长名称规则(long name)
4、在短名称后追加两个下划线(__)和参数描述符
提示: 使用javap命令可以生成符合命名约定的头文件。
2.动态注册:
除了基于约定的静态注册外,还可以通过动态注册来确定 native 方法和 JNI 函数的映射关系。动态注册需要使用 RegisterNatives(…) 函数。
RegisterNatives(…) 函数:
一般会在JNI_Onload(…)函数中执行动态注册,例如:
android_media_MediaPlayer.cpp
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
...
if (register_android_media_MediaPlayer(env) < 0) {
ALOGE