写在前面
这对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