JNI动态注册

来源:互联网 发布:网络营销策划案 汽车 编辑:程序博客网 时间:2024/06/12 01:24

概述

jni简单的说就是java调用c,注册c的方法有两种,一种是静态注册,一种是动态注册。静态注册就是通过javah生成.h文件来实现,不是本文重点。动态注册通过JNI_OnLoad来注册native方法,下面直接上代码。

java层

public class FileUtils {    static {        System.loadLibrary("native-lib");    }    public static native void diff(String path, String pattern_Path, int file_num);}

直接新建一个类来管理native方法,其他activity的代码就不贴了,直接调用即可。

native层

调用System.loadLibrary(“native-lib”);会进入JNI_OnLoad,通过这个方法来注册。

jint JNI_OnLoad(JavaVM *vm, void *reserved) {    JNIEnv *env = NULL;    jint result = -1;    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4)) {        return -1;    }    assert(env != NULL);    registerNatives(env);    return JNI_VERSION_1_4;}

这个方法主要是通过JavaVM 去获取JNIEnv ,有了这个指针就可以注册native方法了,在看registerNatives方法之前需要做一些准备工作。

JNIEXPORT void JNICALL native_diff        (JNIEnv *, jclass, jstring, jstring, jint) {    LOGI("%s\n", "注册成功");}static const JNINativeMethod gMethods[] = {        {                "diff", "(Ljava/lang/String;Ljava/lang/String;I)V", (void *) native_diff        }};

首先声明一个方法,这个方法的名字可以任意指定,这个就是native注册的方法,接着声明一个结构体数组
gMethods[],里头包含了注册的对应关系。JNINativeMethod 的声明

typedef struct {    const char* name;    const char* signature;    void*       fnPtr;} JNINativeMethod;

name是java层的方法名,signature是对应的方法指针,fnPtr是c层的函数指针,做一一对应关系。
最后看看registerNatives方法。

int registerMainNative(JNIEnv *env) {    LOGI("register main start");    jclass clz = env->FindClass("com/example/ty/sourceproject/MainActivity");    if (NULL == clz) {        LOGI("mainclass is null");        return JNI_FALSE;    }    if (env->RegisterNatives(clz, mainMethod, NELEM(mainMethod)) < 0) {        LOGI("registernatives error");        return JNI_FALSE;    }    return JNI_TRUE;}

方法很简单就是通过env来注册多个方法,NELME和LOGI的宏定义是这样的

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

工作作完,剩下的直接调用逻辑即可。

总结

动态注册主要就是3步:
1.通过JNI_OnLoad获取env指针。
2.编写native方法以及对应的结构体数组
3.注册方法

关于动态注册和静态注册的优缺点:

静态注册:
优点:每个class都需要使用javah生成一个头文件,并且生成的名字很长书写不便;初次调用时需要依据名字搜索对应的JNI层函数来建立关联关系,会影响运行效率
缺点:用javah 生成头文件方便简单

动态注册:
优点:使用一种数据结构JNINativeMethod来记录java native函数和JNI函数的对应关系
移植方便(一个java文件中有多个native方法,java文件的包名更换后)
缺点:使用麻烦