「本文已参与好文召集令活动,点击检查:后端、大前端双赛道投稿,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”,其间分为两部分,括号内标明的是参数,括号右侧标明的是回来值;
①、数据类型映射
根柢数据类型
②. 数组引用类型
如果是一维数组则遵循下表,如果是二维数组或更高维数组则对应的 native 类型为 jobjectArray,域描绘符中运用 ‘[’ 的个数标明维数
③. 政策引用类型
关于其它引用类型,即 java 中的政策,其映射规矩为
④. 政策数组引用类型
如果是一维数组则遵循下表,如果是二维数组或更高维数组则对应的数组词 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的知识点和高级使用