JNI和NDK开发之动态注册JNI函数
什么是静态注册
静态注册是根据JNI的方法名字来实现与Java方法的映射对应关系。如下所示,方法名的组成是根据JNIEXPORT jstring JNICALL Java_+包名+_类名+_方法名
组成。包名直接要用_连接。
JNIEXPORT jstring JNICALL Java_com_common_secure_SecureProtocol_encrypt(JNIEnv *, jobject, jstring)
- 优点
可以使用javah命令实现头文件和函数名的生成。
- 缺点
因为方法的名称辨识度较高,所以方法安全性不高,使用IDA反调试so文件的时候很容易暴露接口信息。
什么是动态注册
动态注册是使用RegisterNatives
方法来实现与Java方法的映射对应关系。函数原型:
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, jint nMethods)
jclass clazz
参数是java对应的类JNINativeMethod* methods
是java类对应的函数
JNINativeMethod
是一个结构体,结构如下
ypedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
结构体的第一个参数name
是java 方法名;第二个参数signature
用于描述方法的参数与返回值;第三个参数fnPtr
是函数指针,指向 jni 函数;
其中,第二个参数signature
使用字符串记录方法的参数与返回值,具体格式形如()V
、(II)V
,其中分为两部分,括号内表示的是参数,括号右侧表示的是返回值;
JNINativeMethod nativeMethods[] = {
{"encrypt", "(Ljava/lang/String;)Ljava/lang/String;", (void *) encrypt}
};
jint nMethods
是注册的函数的个数
实现动态注册
在Java层MainActivity中创建一个方法
public native String encrypt(String data);
在JNI_OnLoad
方法中实现动态注册
#include <jni.h>
#include <string>
#include <android/log.h>
#include <cassert>
#include <cstdlib>
#include <iostream>
using namespace std;
#define TAG "LOG_CORE:"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
//native 方法实现
jstring encrypt(JNIEnv *env) {
return env->NewStringUTF("JNI动态注册成功");
}
/*
需要注册的函数列表,放在JNINativeMethod 类型的数组中
以后如果需要增加函数,只需在这里添加即可
参数:
1.java中用native关键字声明的函数名
2.签名(传进来参数类型和返回值类型的说明)
3.C/C++中对应函数的函数名(地址)
*/
static JNINativeMethod nativeMethods[] = {
{"encrypt", "(Ljava/lang/String;)Ljava/lang/String;", (void *) encrypt}
};
//此函数通过调用RegisterNatives方法来注册我们的函数
static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *nativeMethods,int methodsNum) {
jclass clazz;
//找到声明native方法的类
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
//注册函数 参数:java类 所要注册的函数数组 注册函数的个数
if (env->RegisterNatives(clazz, nativeMethods, methodsNum) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
static int registerNatives(JNIEnv *env) {
//指定类的路径,通过FindClass 方法来找到对应的类
const char *className = "com/rzr/jni/register/MainActivity";
return registerNativeMethods(env, className, nativeMethods,
sizeof(nativeMethods) / sizeof(nativeMethods[0]));
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
LOGE("JNI_OnLoad 初始化");
JNIEnv *env = NULL;
jint result = -1;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
assert(env != NULL);
//注册函数 registerNatives ->registerNativeMethods ->env->RegisterNatives
if (!registerNatives(env)) {
return -1;
}
result = JNI_VERSION_1_4;
return result;
}
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/25/dynamic-registration-of-jni-functions-for-jni-and-ndk-development/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论