JNI和NDK开发(3)_动态注册JNI函数

本文深入解析JNI函数的动态注册机制,对比静态注册,探讨其安全性和灵活性。介绍RegisterNatives方法及其实现步骤,包括JNINativeMethod结构体的使用,以及在JNI_OnLoad中的动态注册过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一和第二篇讲解的是JNI函数的静态注册,这一篇将讲述如何实现JNI函数的动态创建。
本文概览
1、什么是静态注册
2、什么是动态注册
3、实现动态注册

什么是静态注册

静态注册是根据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)

1、jclass clazz参数是java对应的类
2、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}
};

3、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;
}

参考:
https://blog.csdn.net/qq_20404903/article/details/80662316
https://www.jianshu.com/p/1d6ec5068d05

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ruiurrui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值