ReactNative4Android源碼分析二JNI智能指針模板

上傳人:新**** 文檔編號:61941042 上傳時間:2022-03-13 格式:DOCX 頁數(shù):9 大?。?0.88KB
收藏 版權(quán)申訴 舉報 下載
ReactNative4Android源碼分析二JNI智能指針模板_第1頁
第1頁 / 共9頁
ReactNative4Android源碼分析二JNI智能指針模板_第2頁
第2頁 / 共9頁
ReactNative4Android源碼分析二JNI智能指針模板_第3頁
第3頁 / 共9頁

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《ReactNative4Android源碼分析二JNI智能指針模板》由會員分享,可在線閱讀,更多相關(guān)《ReactNative4Android源碼分析二JNI智能指針模板(9頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、ReactNative4Android源碼分析二:JNI智能指針JNI智能指針之介紹篇:JNI指針通常的app中,JNI提供的native函數(shù)主要充當Java類的擴展,邏輯層在Java端,JNI端較少使用OOP的設(shè)計思想。而對于native端功能較重的模塊,例如開源的閱讀器FBReader,native端與Java端有較多交互,即native會主動創(chuàng)建Java對象并調(diào)用它們的方法以實現(xiàn)功能,這時就需要考慮將native至Java的操作與訪問框架化,形成更高層次的封裝,以避免直接使用原始的JNI反射API集去操作Java對象。對于ReactNativeForAndroid而言,這套訪問框架尤其重

2、要,其核心就是JNI智能指針這個基本數(shù)據(jù)類型。它的實現(xiàn)基于C11標準,將先用幾篇對這套native至Java的操作框架進行介紹,為后續(xù)分析打下良好基礎(chǔ)。Native引用首先回顧一下JavaObject(jobject)在native端的三種引用類型:全局引用類似于C語言中的全局變量。使用NewGlobalRef創(chuàng)建,支持跨線程訪問,在調(diào)用釋放DeleteGlobalRef銷毀前,GC無法回收該引用對應(yīng)的javaobject。局部引用概念上與C語言中的局部變量有相似點,但不等同。使用NewLocalRef創(chuàng)建,只能在本線程內(nèi)安全訪問,當創(chuàng)建該引用的native調(diào)用鏈返回至JVM時,未銷毀的局部引

3、用會被JVM自動GC回收。但由于局部引用表容量有限,在返回至JVM前,可以調(diào)用DeleteLocalRef先行銷毀,避免局部引用表超限引起崩潰。弱全局引用與全局引用一樣具有全局作用域,但不會影響GC回收,GC可以隨時回收該引用對應(yīng)的javaobject。使用NewWeakGlobalRef創(chuàng)建,當需要使用時,需要將其升級為全局引用或者局部引用,若已被回收,會返回null,使用DeleteWeakGlobalRef銷毀。該引用類型使用場景較少。由上可見,JNI智能指針的第一個需求,就是要自動管理jobject的生命周期,當進入與離開對應(yīng)作用域時,需要自動調(diào)用對應(yīng)生命周期的創(chuàng)建與銷毀函數(shù)。這在C+

4、中,通常會結(jié)合構(gòu)造與析構(gòu)函數(shù)來進行配對調(diào)用。若功能僅限于此,就與普通的智能指針和mutext鎖管理機制類似了,更重要的需求是在C+層提供與被管理的Java對象鏡像結(jié)構(gòu)的C+對象,形成高層次封裝。這樣,對jobject的訪問與操作就會被封裝在對應(yīng)的鏡像C+對象中,相關(guān)JNI反射調(diào)用的細節(jié)被隱藏,對于其他native模塊而言,與Java層的交互被轉(zhuǎn)化成了與這些鏡像C+對象的交互,整個實現(xiàn)風格OOP化了。這些鏡像C+對象被稱為wrapper對象,其定義代碼位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h

5、文件中。先看一個使用范例:structMyClass:publicJavaClassconstexprstaticautokJavaDescriptor=Lcom/example/package/MyClass;voidfoo()staticautomethod=javaClassStatic()-getMethod(foo);method(self();staticlocal_refcreate(inti)returnnewInstance(i);autoobj=MyClass:create(10);obj-foo();Native的需求是在native端創(chuàng)建com.example.pack

6、age.MyClass這個自定義的Java類的對象,并訪問它的foo方法。實現(xiàn)步驟例子中實現(xiàn)的步驟是:定義java的MyClass的wrapperC+類MyClass,所有wrapper均需要繼承于JavaClass的一個模板實例,并將自身類型做為JavaClass的第一個模板類型參數(shù),以供JavaClass獲取具體wrapper的類型。給static成員變量kJavaDescriptor賦值為對應(yīng)Java類的全類名。在wrapper類實現(xiàn)鏡像方法foo(),其會獲取jclass的包裝類JClass對象,并獲取jmethod的包裝類JMethod進行調(diào)用。create工廠方法中使用newIns

7、tance構(gòu)建鏡像對象的實例,并將其存至局部智能指針local_ref。這樣就可以通過智能指針訪問wrapperclass提供的foo方法,實現(xiàn)了native至Java的鏡像映射。除了實現(xiàn)對一個java類的的映射,還需要支持對java繼承關(guān)系的映射。若java的MyClass有一子類MyChildClass,native層為其建立的wrapperclass可如下:structMyChildClass:publicJavaClassconstexprstaticautokJavaDescriptor=Lcom/example/package/MyChildClass;這里需要用到JavaClas

8、s的第二個模板參數(shù),設(shè)為MyClass,它是JavaClass疑問這就帶來幾個問題:javaObject與jobject的關(guān)系是什么?為什么智能指針的模板參數(shù)能夠接受多種類型?模板參數(shù)起到的作用是什么?結(jié)尾這些問題將在下一篇智能指針的具體實現(xiàn)篇中解答??偨Y(jié)一下,在ReactNativeforAndroid中,為了簡化native層又Java層的調(diào)用,提供了鏡像結(jié)構(gòu)的wrapperclass,結(jié)合智能指針,將jobject的生命周期管理、javamethod的反射調(diào)用等“樣板”代碼封裝起來,是比較優(yōu)雅的JNI調(diào)用框架。JNI智能指針之實現(xiàn)篇global_ref全局指針與jobject全局引用相對

9、應(yīng),使用場景包括全局變量、成員變量等。這些場景中的jobject,不應(yīng)該從native返回至JVM時釋放,故使用global_ref進行包裹。local_ref局部指針與jobject局部引用相對應(yīng),使用場景包括局部變量、函數(shù)返回值等。當local_ref離開所在作用域時,會釋放自身對jobject的引用,即在析構(gòu)函數(shù)中調(diào)用DeleteLocalRef。weak_ref弱指針與jobject弱全局引用相對應(yīng),在目前版本的RN代碼中未實際使用。alias_ref別名指針,不對持有的jobject進行生命周期管理。即在構(gòu)造與析構(gòu)別名智能指針對象時,不會對持有的jobject進行創(chuàng)建與銷毀的JNI操

10、作。該指針的目的只是為了提供調(diào)用wrapper對象方法的能力,jobject的生命周期由另外的智能指針或直接由JVM進行管理和保證有效性,指針自身不對其額外進行管理。以上智能指針均未提供引用計數(shù)功能,而是通過在智能指針間交換被管理的對象來進行指針轉(zhuǎn)換。智能指針的類圖如下,其代碼位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/References.h智能指針類圖智能指針從上圖可以看出,由于功能區(qū)別,alias_ref別名指針是獨立的一個類,其余的智能指針有共同的父類base_owned_ref。最需要關(guān)注智能指針的存儲,ba

11、se_owned_ref與alias_ref均有同樣的成員變量:detail:ReprStoragestorage_;*storage*_用來存儲創(chuàng)建出來的wrapper對象。這邊的設(shè)計比較巧妙,使用C+中的類型萃取技術(shù)(typetraits)把wrapper對象和jobject關(guān)聯(lián),并將jobject(JNI層),javaobject(RN層),wrapper對象(RN層)三者在內(nèi)存空間上統(tǒng)一了。先看ReprStorage的實現(xiàn):templatestructReprStorageexplicitReprStorage(JniTypeobj)noexcept;voidset(JniTypeob

12、j)noexcept;Repr&get()noexcept;constRepr&get()constnoexcept;JniTypejobj()constnoexcept;private:usingStoragetypenamestd:aligned_storage:type;Storagestorage_;;templatevoidReprStorage:set(JniTypeobj)noexceptnew(&storage_)Repr;ReprAccess:set(get(),obj);templateRepr&ReprStorage:get()noexceptreturn*reinter

13、pret_cast(&storage_);無關(guān)的代碼已被略去。ReprStorage使用私有變量storage_B為存儲空間,尺寸為JObjectBase類的size。從set和get函數(shù)可以看出,storage.內(nèi)存空間的分配是delay到設(shè)值的時候,并將storage_內(nèi)存空間的指針通過reinterpret_cast類型轉(zhuǎn)換為Repr類型。ReprStorage的模板參數(shù)Repr是存儲的wrapperclass的類型,在上章的使用范例中,也就是MyClass:structMyClass:publicJavaClasswrapperclass之間的繼承關(guān)系如下:,明峋:西M.I?:I_Jd

14、*第L_:IGaeCla0lCu9l0fhJBaCli,mewrapperclass繼承關(guān)系JObjectBaseJObjectBase是wrapperclass的根父類,這里顯然存在一個問題:為何能用父類size的內(nèi)存空間去存放任意子類對象?完成繼承關(guān)系的討論后,再回顧這個問題。圖中的CustomJavaClass是一個自定義wrapperclass,它繼承于JavaClass的一個模板實例。所有Java類(除去Object類)的native鏡彳wwrapperclass,均需要繼承于JavaClass的某個模板實例。JavaClass起到兩個橋梁作用:當前定義的wrapperclass與對

15、應(yīng)Java類父類的wrapperclass之間繼承關(guān)系的橋梁;當前定義的wrapperclass與對應(yīng)Java對象的JNIjobject的橋梁。它有三個模板參數(shù),下面是它的類聲明,其代碼位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h:templateclassFBEXPORTJavaClass:publicBasepublic:staticalias_refjavaClassStatic();staticlocal_refjavaClassLocal();protected:/Allocates

16、anewobjectandinvokesthespecifiedconstructor/LikeJClasssgetConstructor,thisfunctioncanonlycheckatruntimeif/theclassactuallyhasaconstructorthatacceptsthecorrespondingtypes./WhileaJavaClass-typecanexposethisfunctiondirectly,itisrecommended/toinsteadtousethistoexplicitlyonlyexposethoseconstructorsthat/t

17、heJavaclassactuallyhas(i.e.withstaticcreate()functions).templatestaticlocal_refnewInstance(Args.args)returndetail:newInstance(args.);javaobjectself()constnoexcept;無關(guān)的代碼已被略去。第一個模板參數(shù)是子wrapperclass的類型。JavaClass的這個模板實例作為這個wrapperclass的父類,提供了創(chuàng)建wrapperclass對象的工廠方法和與對應(yīng)jobject關(guān)聯(lián)的能力,故需要獲得子類的類型。第二個模板參數(shù)是該JavaC

18、lass模板實例的父類。它的默認類型是JObject,代表java.lang.Object類的wrapperclass,是唯一不需要繼承于JavaClass的wrapper對象。JObject提供了對java對象的Class、Field、Method等的訪問封裝方法,wrapperclass通過對它的繼承關(guān)系,獲得了去調(diào)用Javamethod的能力。若wrapperclass無需提供Java類父類方法的調(diào)用能力,則第二個模板參數(shù)保持默認值JObject即可,否則,第二個模板參數(shù)就為Java類父類的wrapperclass,例子在上章中已提供。由于JavaClass幫助構(gòu)建了繼承鏈,wrappe

19、rclass具備了提供父java類的native鏡像方法的能力。第三個模板參數(shù)是定義的wrapperclass對應(yīng)Java對象的JNIjobject的類型JavaClass會將wrapperclass與jobject建立起綁定關(guān)系。根據(jù)jobject的具體類型,會分兩種情況,如果為JNI預定義的jobject類型,例如jclass、jthrowable、jarray、jstring等,第三個模板參數(shù)就是它們,RN中已經(jīng)預定義了它們的wrapperclass。例如:classFBEXPORTJString:publicJavaClass另外一種情況就是非預定義類型,也就是jobject這個通用類

20、型(jclass、jstring等預定義類型也是它的子類),這時第三個參數(shù)就應(yīng)為默認值void。即不由模板參數(shù)指定jobject的具體子類,而是使用wrapperclass內(nèi)部嵌套定義的擴展子類。瀏覽jobject內(nèi)部定義前,先回顧剛才的存儲問題。既然sizeof(JObjectBase)的內(nèi)存空間能夠正確放置任意wrapperclass子類的實例,就說明子類所占的內(nèi)存空間與根類JObjectBase一樣。而對于一個C+類而言,對象的size就是所有非static成員變量的size之和(需考慮內(nèi)存對齊),這就約束了wrapperclass作為子類不能額外聲明任何非static成員變量,才能與根

21、父類JObjectBase保持size的一致。從wrapperclass的設(shè)計目的考慮,它只是Java類在native空間的鏡像類和接口包裝類,業(yè)務(wù)邏輯應(yīng)由調(diào)用者實現(xiàn),wrapperclass自身應(yīng)該是無狀態(tài)的,所以不允許wrapperclass定義非static成員變量是合理的。智能指針存儲的是wrapperclass的實例,wrapperclass中存儲的是jobject,從以上分析可以知道,存儲的jobject成員變量只能由根父類JObjectBase去承載。下面是JObjectBase的類定義,代碼位于ReactAndroid/src/main/jni/first-party/fb/i

22、nclude/fb/fbjni/References-forward.h:structJObjectBasejobjectget()constnoexcept;voidset(jobjectreference)noexcept;jobjectthis_;JObjectBase是一個簡單的bean類,唯一的成員變量就是jobject,這也是所有wrapperclass唯一的成員變量。在JavaClass模板類中,為了實現(xiàn)jobject與wrapperclass兩者的關(guān)聯(lián),對jobject做了內(nèi)部擴展定義。為了理解它,先回顧下jobject在jni.h中的原始定義:class_jobject;ty

23、pedef_jobject*jobject;class_jstring:public_jobject;所以,jobject就是個指針,指向javaobject在JVM中的內(nèi)存對象,對于像*dexposed*這樣的熱修復框架,就是利用這些指針去修改java對象模型來改變javamethod的屬性以實現(xiàn)hook。這里的定義_jobject是空類,只是為了定義指針語法以在JNI中去引用內(nèi)存對象,并不意味Java內(nèi)存對象真的是個空對象,真正定義是JVM內(nèi)部的、平臺相關(guān)的,而不需要將實現(xiàn)細節(jié)暴露給JNI。在JavaClass中,對jobject的擴展定義javaobject類型如下:templatecl

24、assFBEXPORTJavaClass:publicBaseusingJObjType=typenamedetail:JTypeFor;public:using_javaobject=typenameJObjType:_javaobject;usingjavaobject=typenameJObjType:javaobject;namespacedetailtemplatestructJTypeForstatic_assert(std:is_base_ofstd:remove_pointer:type,typenamestd:remove_pointer:type:value,);using

25、_javaobject=typenamestd:remove_pointer:type;usingjavaobject=JType;templatestructJTypeFor/JNIpatternforjobjectassignablepointerstruct_javaobject:Base:_javaobject/Thisallowsustomapbacktothedefiningtype(inReprType,for/ple).typedefTJniRefRepr;usingjavaobject=_javaobject*;在JavaClass中,將jobject拓展定義為javaobj

26、ectjavaobject是typenameJObjType:javaobject,也就是JTypeFor的一個模板實例類型的成員指針類型。以例子代碼中的MyClass為例,父類JavaClass接收的三個模板參數(shù)分別為MyClass,JObject,void,JTypeFor的三個模板參數(shù)也依次是它們,由于第三個參數(shù)是void,故會使用上面代碼中的JTypeForstructJTypeForstruct_javaobject:JObject:_javaobjecttypedefMyClassJniRefRepr;usingjavaobject=_javaobject*;可看到_javaobj

27、ect繼承于JObject:_javaobject,它的定義如下:typedef_jobject_javaobject;typedef_javaobject*javaobject;JObject:_javaobject就是jni.h中的object類型,故MyClass中的avaobject又_jobject的繼承擴展,只是添加了一個嵌套類成員類型JniRefRepr,來指向當前_javaobject所對應(yīng)的wrapperclass類型,這就是所謂的C+類型萃取技術(shù)。因為_jobject是用來指向Java內(nèi)存對象,所以不能用繼承后添加成員變量的方式來擴展,否則會破壞內(nèi)存對象,而成員類型是屬于類

28、定義,不會占用對象的空間。另,javaobject是指向_javaobject的指針,jobject是指向_jobject的指針。問題解答現(xiàn)在來解答上章的三個問題javaobject與jobject的關(guān)系是什么?兩者本質(zhì)是一樣的,都是指向java內(nèi)存對象的JNI引用;區(qū)別是javaobject是jobject繼承擴展,繼承后的javaobject擁有一個類成員類型變量,指向?qū)?yīng)的wrapperclass,使得兩者彼此關(guān)聯(lián)。從內(nèi)存上看,sizeof(JObjectBase)=sizeof(任意wrapperclass)=sizeof(jobject)=sizeof(javaobject),達到了

29、有機的統(tǒng)一。為什么智能指針的模板參數(shù)能夠接受多種類型?在上章例子中,與傳遞了不同模板參數(shù),從語法上看區(qū)別很大,但在內(nèi)部實現(xiàn)時,都會進行類型萃取。即無論傳遞的何種類型,都會萃取出對應(yīng)的ReprType(wrapperclass類型)、JniType(javaobject類型)。javaobject類是wrapperclass的成員類型,故從wrapperclass可以獲得對應(yīng)javaobject引用的類型;javaobject類的成員類型是wrapperclass,故從javaobject業(yè)可以獲得對應(yīng)wrapperclass的類型。在框架中提供了兩個工具來進行類型萃取和轉(zhuǎn)換:/GivenT,e

30、itherajobject-liketypeoraJavaClass-derivedtype,ReprType/isthecorrespondingJavaClass-derivedtypeandJniTypeisthe/jobject-liketype.templateusingReprType=typenamedetail:RefReprType:type;templateusingJniType=typenamedetail:JavaObjectType:type;ReprType用來從模板參數(shù)中獲得wrapperclass類型,JniType用來從模板參數(shù)中獲得javaobject類型

31、。通過這樣的機制,兩個類型彼此打通,故無論傳遞何種模板參數(shù),智能指針都能正確存儲對應(yīng)類型的wrapperclass。模板參數(shù)起到的作用是什么?從上可以了解到,智能指針的模板參數(shù)用來獲取存儲的wrapperclass的類型。對于local_ref和global_ref,它們由于都是強引用,可以用來直接調(diào)用存儲的wrapperclass提供的方法,所以它們的實現(xiàn)模板類basic_strong_ref在base_owned_ref提供的存儲功能的基礎(chǔ)上,繼承擴展提供了指針操作符的重載,以將對智能指針的訪問轉(zhuǎn)發(fā)到wrapper對象上,代碼如下:templateinlineautobasic_stron

32、g_ref:operator-()noexcept-Repr*return&storage_.get();templateinlineautobasic_strong_ref:operator-()constnoexcept-constRepr*return&storage_.get();重載實現(xiàn)中,從storage.中獲得存儲的wrapperclass實例返回即可。對于模板參數(shù)Alloc,則是分配器的類型,封裝了創(chuàng)建、銷毀jobject的操作,由智能指針在構(gòu)造和析構(gòu)時調(diào)用,實現(xiàn)jobject生命周期的管理??偨Y(jié)總結(jié)一下,本篇簡述了wrapperclass與智能指針的主干實現(xiàn)。wrapperclass擴展jobject至javaobject,使類型彼此關(guān)聯(lián);構(gòu)建了繼承鏈,將對javamethod的反射調(diào)用和java類自身的繼承關(guān)系分解在鏈路的不同節(jié)點。智能指針通過類型萃取負責將jobject存儲至正確的wrapper實例,以對外提供鏡像方法;結(jié)合構(gòu)造與析構(gòu)函數(shù),自動進行jobject的生命周期管理。

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!