寫在前面
這對JNI來說并不陌生。它的全稱是Java原生接口,即Java原生接口。
JNI不僅是Android獨有的,也屬于java平臺,它允許Java虛擬機(jī)中運行的Java代碼與其他編程語言(如c、c++和匯編語言)編寫的程序和庫進(jìn)行交互。
JNI呼叫姿勢:爪哇->:JNI->;C/C++(SO庫)
在Android平臺上,使用JNI封裝硬件相關(guān)操作,這樣就可以通過Java調(diào)用相關(guān)的JNI模塊來調(diào)用硬件。
下面我們將重點介紹以下內(nèi)容:
1.java代碼編譯和執(zhí)行過程
2.jni套路使用姿勢
3.so加載過程(jni執(zhí)行過程,注冊方法原理)
4的功能及實現(xiàn)。JNIEnv
Java代碼編譯和執(zhí)行過程
編譯和執(zhí)行java代碼的過程包括兩個命令:javac和java
1.首先,通過javac編譯java代碼,生成類字節(jié)碼文件
2.javacTestCode.java-& gt;TestCode.class
3.然后通過java命令執(zhí)行類字節(jié)碼
4.javaTestCode.class
在java命令執(zhí)行過程中,首先啟動虛擬機(jī),將TestCode類信息加載到內(nèi)存中,然后由執(zhí)行引擎執(zhí)行主方法。
JVM的邏輯內(nèi)存模型如下:
JNI的通用姿勢
在java層通過native關(guān)鍵字創(chuàng)建本地方法,如下:(成員方法、static方法)public classJNIMethods{靜態(tài){
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);
}
創(chuàng)建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時將執(zhí)行此方法
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 "/>
類中的本地方法加載過程:
本地方法調(diào)用過程:
JNIEnv的功能及實現(xiàn)
JNIEnv是JNI指針接口,我們通常通過它來調(diào)用和操作java對象,它提供了操作Java對象的所有API。
那么JNIEnv是什么時候創(chuàng)建的,如何操作Java對象呢?我們來看看它的具體實現(xiàn)吧~
首先,讓我們看看線程是如何創(chuàng)建的:
java/lang/Thread。爪哇島
新線程()。start()->VMThread.create()
publicsynchronizedvoidstart(){
checkNotStarted();
hasBeenStarted = true
VMThread.create( this,stack size);// VMThread創(chuàng)建
}
/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 },//線程創(chuàng)建方法
{ "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);//創(chuàng)建線程
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);//創(chuàng)建線程
// ......
}
/*
*用于線程的pthread入口函數(shù)從解釋的代碼開始。
*/
static void * Interthreadstart(void * arg)
{
// ......
self->;jnie NV = dvmcreatejniev(self);//創(chuàng)建jniEnv
// ......
returnNULL
}
JNIEnv的建立
/dalvik/vm/jni.cpp
dvmCreateJNIEnv()
jniev * dvmcreatejniev(Thread * self){
javaxmext * VM =(javaxmext *)gdvmjni . jnivm;
//……
新環(huán)境->;function table = & amp;簽名接口;//接口功能
// ......
return(JNIEnv *)Newenv;
}
static construct JNINativeInterface gNativeInterface = {
定義一個類,
FindClass,
// ......
CallVoidMethod,
// ...
GetFieldID,
GetObjectField,
// ...
CallStaticIntMethod,
// ......
};
//方法的具體實現(xiàn)(下面是callVoidMethodA()的具體實現(xiàn))
#定義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參數(shù);
JValue結(jié)果;
method = dvmgetvirtuized method(obj->;clazz,(Method *)Method);
if(meth == NULL) {
return _ retfail
}
va_start(args,methodID
dvmcallmethov(ts。self(),meth,obj,true,& ampresult,args);//方法調(diào)用
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,
法,自我);//執(zhí)行方法
TRACE_METHOD_EXIT( self,METHOD);
}
//……
}
JNIEnv是Thread創(chuàng)建的時候創(chuàng)建的,所以它屬于線程,不能被線程共享。該方法最終通過堆棧調(diào)用...相關(guān)方法。至此,整個過程已經(jīng)分析完畢。
結(jié)論
通過以上分析,我們知道JNI是如何在java和本地代碼之間搭建橋梁和溝通的。
使用JNI時,您應(yīng)該注意:
1.顯式注冊和隱式注冊的區(qū)別
2.JNI方法的使用
3.3的使用。JNIEnv
4.4的命名。JNI方法,以及extern“c”的功能(告訴編譯器這部分代碼應(yīng)該用c編譯),等等
所有人都在看
歡迎來到安卓巴士博客區(qū)投稿,分享中科技成長
期待巴友的留言,一起探討學(xué)習(xí)
1.《jni 一文深入理解 JNI實現(xiàn)機(jī)制》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識,僅代表作者本人觀點,與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《jni 一文深入理解 JNI實現(xiàn)機(jī)制》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。
3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/tiyu/673264.html