当前位置:首页 > 体育

jni 一文深入理解 JNI实现机制

写在前面

这对JNI来说并不陌生。它的全称是Java原生接口,即Java原生接口。

JNI不仅是Android独有的,也属于java平台,它允许Java虚拟机中运行的Java代码与其他编程语言(如c、c++和汇编语言)编写的程序和库进行交互。

JNI呼叫姿势:爪哇->:JNI->;C/C++(SO库)

在Android平台上,使用JNI封装硬件相关操作,这样就可以通过Java调用相关的JNI模块来调用硬件。

下面我们将重点介绍以下内容:

1.java代码编译和执行过程

2.jni套路使用姿势

3.so加载过程(jni执行过程,注册方法原理)

4的功能及实现。JNIEnv

Java代码编译和执行过程

编译和执行java代码的过程包括两个命令:javac和java

1.首先,通过javac编译java代码,生成类字节码文件

2.javacTestCode.java-& gt;TestCode.class

3.然后通过java命令执行类字节码

4.javaTestCode.class

在java命令执行过程中,首先启动虚拟机,将TestCode类信息加载到内存中,然后由执行引擎执行主方法。

JVM的逻辑内存模型如下:

JNI的通用姿势

在java层通过native关键字创建本地方法,如下:(成员方法、static方法)public classJNIMethods{

静态{

system . LoadLibrarY(" test-JNI ");

}

//隐式注册

publicationstringfromjni();

publicationstatinativestring testParams(int jint,String jstring,Object jobject,Object[] arrayObject,list list);

//显式注册

publicationStringStringFromjNidis();

publicationstatinativestring testparams dis(int jint,String jstring,Object jobject,Object[] arrayObject,list list);

}

创建c层代码,并注册本地方法#include

#包括

#包含“common.h”

jstring StringFromjNidis(JNIEnv * env,job object jobj);

jstring TestParamesdis(JNIEnv * env,jclass type,jint jint_,jstring jstring_,jobject jobject _,jobjectArray objectArray,job object list);

staticmethodid methodID _ toString;

//显式注册

staticninativmethod gmmethods[]= {

{ "stringFromJNIDis "、"()Ljava/lang/String;",(void*) stringFromJNIDis},

{ " testParamsDis ",(ILJava/lang/String;ljava/lang/Object;【Ljava/lang/Object;ljava/util/List;)Ljava/lang/String;”,(void *)TestParamesdis }

};

static internativemethods(JNIEnv * env,constchar*className,JNINativeMethod *methods,intnMethods){

jclass clazz

clazz = env->。find class(CLaSS name);

if(clazz == NULL) {

returnJNI _ FALSE

}

if(env->;登记措施(声明、方法、方法)& lt0) {

returnJNI _ FALSE

}

returnJNI _ TRUE

}

voidappendString(JNIEnv *env,char*dest,jstring tmpStr){

if(tmpStr == NULL) {

返回;

}

constchar*tmpString = env->。GetStringUTFChars(tmpStr,0);

strcat(dest,TMPstring);

env->;ReleaseStringUTFChars(tmpStr,TMPstring);

}

//加载so时将执行此方法

JNIEXPORT jint JNICALL JNI _(JavaTM * VM,void*reserved){

LOGD(“test-JNI . CPP JNI _”;

JNIEnv * env = NULL

if(vm->;GetEnv((void * *)& amp;env,JNI_VERSION_1_4)!= JNI_OK) {

return-1;

}

if( NULL== env) {

return-1;

}

jclass clazz = env->。find class(" Java/lang/Object ");

method id _ ToString = env->;GetMethodID(clazz," toString "/>

类中的本地方法加载过程:

本地方法调用过程:

JNIEnv的功能及实现

JNIEnv是JNI指针接口,我们通常通过它来调用和操作java对象,它提供了操作Java对象的所有API。

那么JNIEnv是什么时候创建的,如何操作Java对象呢?我们来看看它的具体实现吧~

首先,让我们看看线程是如何创建的:

java/lang/Thread。爪哇岛

新线程()。start()->VMThread.create()

publicsynchronizedvoidstart(){

checkNotStarted();

hasBeenStarted = true

VMThread.create( this,stack size);// VMThread创建

}

/dalvik/VM/native/Java _ lang _ VMthread。cpp

dalvik _ Java _ lang _ VMthread _ create()->Thread.dvmCreateInterpThread()

constdalviknatimemethod dvm _ Java _ lang _ VMThread[]= {

{“create”,”(Ljava/lang/Thread;J)V ",

dalvik _ Java _ lang _ VM thread _ create },//线程创建方法

{ "currentThread "、"()Ljava/lang/Thread;",

dal vik _ Java _ lang _ VMthread _ Current thread },

//……

};

staticvoidalvik _ Java _ lang _ VMThread _ create(constu 4 * args,JValue* pResult)

{

//……

dvmcreateinterthread(threadObj,(int)stack size);//创建线程

RETURN _ VOID();

}

/dalvik/vm/Thread。cpp

dvmcreateinterthread()->;interthreadstart()->jni.dvmCreateJNIEnv()

bool dvmcreateinterthread(Object * threadObj,intreqStackSize)

{

// ......

thread * new thread = allocThread(stack size);

// ......

int cc = pthread _ create(& amp;threadHandle,& ampthreadAttr,interpThreadStart,new thread);//创建线程

// ......

}

/*

*用于线程的pthread入口函数从解释的代码开始。

*/

static void * Interthreadstart(void * arg)

{

// ......

self->;jnie NV = dvmcreatejniev(self);//创建jniEnv

// ......

returnNULL

}

JNIEnv的建立

/dalvik/vm/jni.cpp

dvmCreateJNIEnv()

jniev * dvmcreatejniev(Thread * self){

javaxmext * VM =(javaxmext *)gdvmjni . jnivm;

//……

新环境->;function table = & amp;签名接口;//接口功能

// ......

return(JNIEnv *)Newenv;

}

static construct JNINativeInterface gNativeInterface = {

定义一个类,

FindClass,

// ......

CallVoidMethod,

// ...

GetFieldID,

GetObjectField,

// ...

CallStaticIntMethod,

// ......

};

//方法的具体实现(下面是callVoidMethodA()的具体实现)

#定义CALL _ VIDEL(_ ctype,_jname,_retfail,_retok,_isref)

static _ ctype Call # # _ jname # # Method(JNIEnv * env,jobject jobj,

jmethodmethod,...)

{

ScopedJniThreadState ts(env);

Object * obj = dvmDecodeIndirectRef。self(),jobj);

const method * method;

va_list参数;

JValue结果;

method = dvmgetvirtuized method(obj->;clazz,(Method *)Method);

if(meth == NULL) {

return _ retfail

}

va_start(args,methodID

dvmcallmethov(ts。self(),meth,obj,true,& ampresult,args);//方法调用

va _ end(args);

if(_ isref & amp;& amp!dvmCheckException(ts。self()))

result . l =(Object *)AddLocalReference(ts。self(),result . l);

return _ retok

}

CALL _ VIRTUAL(job object,Object,NULL,(job Object)result . l,true);

// ......

/dalvik/vm/interp/Stack.cpp

JNIEnv。CallVoidMethodA() ->Stack.dvmCallMethodA()

void dvmCallMethodA(Thread* self,constMethod*方法,Object* obj,

bool fromJni,JValue * pResult,constjvalue* args)

{

// ......

if(dvmIsNativeMethod(method)) {

TRACE_METHOD_ENTER( self,METHOD);

(*方法->;native func()((U4 *)self->;inter save . cur frame,pResult,

法,自我);//执行方法

TRACE_METHOD_EXIT( self,METHOD);

}

//……

}

JNIEnv是Thread创建的时候创建的,所以它属于线程,不能被线程共享。该方法最终通过堆栈调用...相关方法。至此,整个过程已经分析完毕。

结论

通过以上分析,我们知道JNI是如何在java和本地代码之间搭建桥梁和沟通的。

使用JNI时,您应该注意:

1.显式注册和隐式注册的区别

2.JNI方法的使用

3.3的使用。JNIEnv

4.4的命名。JNI方法,以及extern“c”的功能(告诉编译器这部分代码应该用c编译),等等

所有人都在看

欢迎来到安卓巴士博客区投稿,分享中科技成长

期待巴友的留言,一起探讨学习

1.《jni 一文深入理解 JNI实现机制》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《jni 一文深入理解 JNI实现机制》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/tiyu/673264.html

上一篇

深圳海关总署 海关总署“国门利剑2020”专项行动 38.8亿元!特大走私钻石案告破

下一篇

新型装修材料 2018年10大装修新兴材料

排列组合题型方法总结 高考数学6大必考题型+解题技巧分析全总结,大题必考题型!

  • 排列组合题型方法总结 高考数学6大必考题型+解题技巧分析全总结,大题必考题型!
  • 排列组合题型方法总结 高考数学6大必考题型+解题技巧分析全总结,大题必考题型!
  • 排列组合题型方法总结 高考数学6大必考题型+解题技巧分析全总结,大题必考题型!
女生肚子疼怎么办 女生来例假肚子疼怎么办? 什么方法可缓解经痛?

女生肚子疼怎么办 女生来例假肚子疼怎么办? 什么方法可缓解经痛?

女性月经前后小腹、腰骶疼痛,严重者腹痛严重,面色苍白,手脚冰凉,甚至晕厥,称为痛经。疼痛往往持续几个小时或者1-2天。一般在月经量通畅后腹痛缓解。年轻女性比较常见,是常见的妇科疾病之一。中医...

修改病句题目及答案 小学语文修改病句符号、方法及练习题100题(附答案)

修改病句题目及答案 小学语文修改病句符号、方法及练习题100题(附答案)

修改病句是小学语文学科中不可忽视的重要内容,也是小学教学中常见而重要的内容。小学生掌握了修改病句的方法后,在造句和写文章时可以避免或少犯错误,同时可以及时发现和纠正文章中的病句,对以后的写作...

病句练习题及答案 小学语文修改病句符号、方法及练习题100题(附答案)

病句练习题及答案 小学语文修改病句符号、方法及练习题100题(附答案)

修改病句是小学语文学科中不可忽视的重要内容,也是小学教学中常见而重要的内容。小学生掌握了病句的修改方法后,在造句和写文章时可以避免或少犯错误,同时可以及时发现和纠正文章中的病句,对以后的写作...

雀斑治疗 雀斑的有效治疗方法有哪些

  • 雀斑治疗 雀斑的有效治疗方法有哪些
  • 雀斑治疗 雀斑的有效治疗方法有哪些
  • 雀斑治疗 雀斑的有效治疗方法有哪些

蓝月传奇新手礼包 蓝月传奇礼包大全 蓝月传奇礼包激活码领取方法

  • 蓝月传奇新手礼包 蓝月传奇礼包大全 蓝月传奇礼包激活码领取方法
  • 蓝月传奇新手礼包 蓝月传奇礼包大全 蓝月传奇礼包激活码领取方法
  • 蓝月传奇新手礼包 蓝月传奇礼包大全 蓝月传奇礼包激活码领取方法
防沉迷怎么解除 王者荣耀防沉迷怎么修改 解除实名认证健康系统的方法

防沉迷怎么解除 王者荣耀防沉迷怎么修改 解除实名认证健康系统的方法

如何修改王者反沉迷的荣耀,以及去除反沉迷的两种方法。防沉迷是王者荣耀最近推出的监控系统。有些未成年玩家每天最多只能玩1~2个小时,这让很多没注意绑定身份证的玩家感到很苦恼。接下来我们来看看如...

去除口臭的方法 怎样去除口臭?最简单的去除口臭的方法

  • 去除口臭的方法 怎样去除口臭?最简单的去除口臭的方法
  • 去除口臭的方法 怎样去除口臭?最简单的去除口臭的方法
  • 去除口臭的方法 怎样去除口臭?最简单的去除口臭的方法