「本文已参与好文召集令活动,点击检查:后端、大前端双赛道投稿,2万元奖池等你挑战!」

本文章已在群众号【Android开发编程】宣告

前语小计

1、jni与ndk的根柢知识点前面文章都讲过了,不指针式万用表图片懂的,可以在群众号主页看;

2、jni中常用的办法比如:类、办法、数组、字符串等前面也阐明过了;

3、这篇文章阐明jni中函数的注册和c++调用java的知识点;

一. JNI函数注册

1、jni函数注解知识点介绍

JNI技能是Java世界与Native世界的通讯桥梁,详细到代码,Java层的代码怎样同Native层的代码进行调用的呢?咱们都知道,在调用native办法之前,首先要调用System.loadLibrary接口加载一个完毕了native办法的动态库才干正常拜访,不然就会抛出jjava难学吗ava.lang.UnsatisfiedLinkError异常 。 那么,在Java中调用某个native办法时,JVM是经过什么办法,能正确的找到动态库中C/C++完毕的那个native函前端开发是干什么的数呢?

JVM查找native方后端是做什么的法有java难学吗两种办法;

依照JNI规范的命名规矩,调用JNI供给的RegisterNatives函数,将本地函数注册到JVM中。

第一种办法,可用运用javah指针万用表的使用办法东西按后端是做什么的照Java类中界说的native办法,依照JNI规范的命名规矩的办法自动生成Jni本地C/C++头文件。

第二种办法则需求在本地库的JNI_OnLoad函数中调用Regist前端开发需求学什么erNatives来动态注册。

JNI函数注册是将Java层声明的Native办法同实践的Nativ后端开发需求掌握哪些知识e函数绑定起来的完毕办法,也就是说,只需经过JNI函数注册机制注册了本当地,Java层就可以直接调用界说的这些本地方数组公式法了。对应上述JVM查找java面试题native办法的两种办法,JNI函数注册办法一般分为静态注册和动态注册两种办法。

2、静态注册

原理:根据函数名来树立 java 办法与 JNI 函数的一一对应联络;

完毕流程:

编写 j指针ava 代码;

运用 javah 指令生成对应的 .h 文件;

对 .h 中的声明进行完毕;前端面试题

坏处:

编写不方便,JNI 办法姓名有必要遵循规矩且姓名很长;

编写进程进程多,不方便;

程序运转功率低,由于初度调用native函数时需求根据根据函数名在JNI层中查找对应的本地函数,然后树立对应联络,这个进程比较耗时;

public class Test {

static {

S后端工程师首要做什么ystem.loadLibrary(“n指针万用表的读法ative-lib”);

}

public native String textFromJni();

}

运用javah生成对应的本地办法头文件。

#include <jni.h>

#ifndef _Includ后端开发需求学什么ed_test

#define _Included前端结构_test

#ifdef __cplusplus

extern “C” {

#endif

JNIEXPORT后端工程师首要做什么 j后端组string JNICALL Java_test_Test_textFromJni

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

3、动态注册

对应与上面的静态注册办法,还有一种动态注册JNI函数的办法,即动态注册。动态注册是当Java层调用Syste后端不支持corsm.loadLibrajavascriptry办法加载so库后,本地库的JNI_OnLoad函数会被调用,在Jjava怎样读NI_OnLoad函指针式万用表怎样读数数中经过调用RegisterNatives函数来完毕本地办法的注册。

原理:运用 RegisterNati指针c言语v后端开发es 办法来注册 java 办法与 JNI 函数的一一对应联络;

完毕流程:

运用结构体 JNINativeMethod 数组记载后端开发是干什么的 java 办法与 JNI 函数的对应联络;

完毕 JNI_OnLoad 办法,在加载动态库后,实行动态注册;

调用 FindClass 办法,获取 java 政策;

调用 RegisterNatives 办法,传入 java 政策,javascript以及 JN前端结构INativeMethod 数组,后端不支持cors以及注册数目完毕数组排序注册;

长处:

流程更加清楚可控;

功率更高;

其间JNINativeMethod结构体用来描绘本地办法结构,其界说如下:

typedef struct {

const char* name; // Jajava初学va办法名

const char*java初学 sjavaeei后端开发需求学什么g前端工程师nature; // Java办法签名

void* fnPtr; // jni本地办法对应的函数指针

} JNINativeMethod;

结构体的第一个参数 name 是java 办法名;

第二个参数 s指针式万用表图片ignature 用于描绘办法的参数与回来值;

第三个参数 fnPtr 是函数指针,指向 jni 函数;

其间,第二个参数 sig前端开发需求学什么na后端是做什么的ture 运用字符串记载Java办法的参数与回来值数组初始化,详细格式形如“()V”、“(II)V”,其间分为两部分,括号内标明的是参数,括号右侧标明的是回来值;

①、数据类型映射

根柢数据类型

Android架构师之路:JNI与NDK编程-函数注册与c++调用java详解(c++音视频编码根底)

②. 数组引用类型

如果是一维数组则遵循下表,如果是二维数组或更高维数组则对应的 native 类型为 jobjectArray,域描绘符中运用 ‘[’ 的个数标明维数

③. 政策引用类型

关于其它引用类型,即 java 中的政策,其映射规矩为

Android架构师之路:JNI与NDK编程-函数注册与c++调用java详解(c++音视频编码根底)

④. 政策数组引用类型

如果是一维数组则遵循下表,如果是二维数组或更高维数组则对应的数组词 native 类型为 jobjectArray,域描绘符中运用 ‘[’ 的个数标明维数

在Java文件中界说本地办法,加载本地so库

packag指针万用表的读法e test.jnitest;

public cl数组ass Test {

static {

System.loadLibrary(“native-lib”);

}

public native Sjavascripttring后端 textFromJni();

}

在JNI_OnLoad函数中注册本地办法后端开发薪酬一般多少

jstring textFromJni(JNIEnv* env, jobject thiz) {

rjava言语eturn env后端开发需求掌握哪些知识->NewStringUTF(“text from jni”);

}

sta后端工程师首要做什么tic JNINativeMethod gMethods[] = {

{“textFro后端工程师首要做什么mJni”, “()Ljava/lang/String;”, (void*)textFromJni}

};

int registerMethod(JNIEnv *env) {

jclass test = env->FindClass(“cc/ccbu/jnitest/Test”)指针式万用表;

return env->RegisterNatives(test, gMethods, sizeofjava模拟器(gMethods)/ siJavazeof(gMet数组词hods[0]));

}

JNIEXPORT ji数组和链表的区别nt JNI数组的长度CALL JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv* env = NULL;

if (vm->GetEnv((void**) &env, JNI前端技能_VERSION_1_6) != JNI_OK) {

return JNI_ERR;

}

if (registerMethod(env) != JNI_OK) {

return JNI_ERR;

}

return JNI_VERSION_1_6;

}

留心java难学吗

在JNI_OnLoad函数的结尾处,咱们一定要有回来值,并且有必要是JNI_VERSION_1_4 或 JNI_VERSION_1_6,也就是JNI的版别后端号,咱们一定要回来正确的版别号,不然体系也是无法数组初始化加载的;

4、c++调用java详解

(1) 找到java对应的Class

(2) 找到要调用的办法的methodID

(3) 在C言语中调用相应办法

①.经过JAVA层的本地办法创立同类政策

进程:

I.经过政策获取类

II.经过类获取类的结构办法的ID

II数组的长度I.根据办法ID和类,创立新政策

JNIEXPORT vo数组去重id JNICALL JAVA_nativeMethod

(JNIEnv *env, jobject thiz,jint i){

jjava言语class clazz = (*env).GetObjectClass(thiz)指针式万用表怎样读数;

jme后端言语thodID mijava模拟器d = (*env).Gjava怎样读etMethodID(clazz,””后端不支持cors,”()V”);

jobject obj = (*env).NewObject(cla前端开发zz,mid);

return;

}

②.经过前端C/C++创数组的长度建不同类方javaee

进程:

I.通javascript过FindClass办法获取需求的类

II.经过类获取类的结构办法的ID

III.根据办法ID和类,创立新政策

JNIEXPORT void JNICALL JAVA_nativeMethod

(JNIEnv *env,后端是做什么的 jobject thiz,jint i){

jclass clazz = (*env).FindClass(“com/x/test/T数组est”);//参数为前端开发类途径

jmethodID mid = (*env).GetMethodID(clazz,””,”()V”);

jobject obj = (*env).NewObjec数组t(clazz,mid);

return;

}

③获取上下文环境JNIEnv后端不支持cors

如果找不到上下文JNIEnv就要获javaapi中文在线看

bool AttachCurrentThread(JavaVM* vm, J后端NIEnv** p_en前端和后端的区别v)javaee{    bool bAttached = false;    switch(vm->GetEnv((void**)p_env, JNI_VERSION_1_4))    {        ca数组的界说se JNI_OK:            break;        case JNI_EDETACHED:            i后端组f (vm->AttachCurrentThread(p_env, 0) < 0)            {                LOGD("%s :test failed!",__func__);                return f后端工程师首要做什么alse;            }            else            {                bAttached = true;            }            break;        case JNI_EVERSION:            LOGE("Invalid java version");            break;    }    return数组的长度 bAttached;}

总结

以上总结了JNI中函数注册的两种办法,在实践使用中都很常见都用得到的,要了解到位才干够;

下次文指针式万用表章会持续阐明关于JNI的知识点和高级使用