歡迎來到裝配圖網(wǎng)! | 幫助中心 裝配圖網(wǎng)zhuangpeitu.com!
裝配圖網(wǎng)
ImageVerifierCode 換一換
首頁 裝配圖網(wǎng) > 資源分類 > DOCX文檔下載  

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

  • 資源ID:61941042       資源大?。?span id="xbrv03s" class="font-tahoma">80.88KB        全文頁數(shù):9頁
  • 資源格式: DOCX        下載積分:0積分
快捷下載 游客一鍵下載
會員登錄下載
微信登錄下載
三方登錄下載: 微信開放平臺登錄 支付寶登錄   QQ登錄   微博登錄  
二維碼
微信掃一掃登錄
下載資源需要0積分
郵箱/手機:
溫馨提示:
用戶名和密碼都是您填寫的郵箱或者手機號,方便查詢和重復下載(系統(tǒng)自動生成)
支付說明:
本站最低充值0.01積分,下載本資源后余額將會存入您的賬戶,您可在我的個人中心查看。
驗證碼:   換一換

 
賬號:
密碼:
驗證碼:   換一換
  忘記密碼?
    
友情提示
2、PDF文件下載后,可能會被瀏覽器默認打開,此種情況可以點擊瀏覽器菜單,保存網(wǎng)頁到桌面,就可以正常下載了。
3、本站不支持迅雷下載,請使用電腦自帶的IE瀏覽器,或者360瀏覽器、谷歌瀏覽器下載即可。
4、本站資源下載后的文檔和圖紙-無水印,預覽文檔經(jīng)過壓縮,下載后原文更清晰。
5、試題試卷類文檔,如果標題沒有明確說明有答案則都視為沒有答案,請知曉。

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

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而言,這套訪問框架尤其重要,其核心就是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時,未銷毀的局部引用會被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+中,通常會結(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文件中。先看一個使用范例:structMyClass:publicJavaClass<MyClass>constexprstaticautokJavaDescriptor="Lcom/example/package/MyClass;"voidfoo()staticautomethod=javaClassStatic()->getMethod<void()>("foo");method(self();staticlocal_ref<javaobject>create(inti)returnnewInstance(i);autoobj=MyClass:create(10);obj->foo();Native的需求是在native端創(chuàng)建com.example.package.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工廠方法中使用newInstance構(gòu)建鏡像對象的實例,并將其存至局部智能指針local_ref。這樣就可以通過智能指針訪問wrapperclass提供的foo方法,實現(xiàn)了native至Java的鏡像映射。除了實現(xiàn)對一個java類的的映射,還需要支持對java繼承關(guān)系的映射。若java的MyClass有一子類MyChildClass,native層為其建立的wrapperclass可如下:structMyChildClass:publicJavaClass<MyChildClass,MyClass>constexprstaticautokJavaDescriptor="Lcom/example/package/MyChildClass;"這里需要用到JavaClass的第二個模板參數(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全局引用相對應(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操作。該指針的目的只是為了提供調(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)注智能指針的存儲,base_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):template<typenameRepr>structReprStorageexplicitReprStorage(JniType<Repr>obj)noexcept;voidset(JniType<Repr>obj)noexcept;Repr&get()noexcept;constRepr&get()constnoexcept;JniType<Repr>jobj()constnoexcept;private:usingStoragetypenamestd:aligned_storage<sizeof(JObjectBase),alignof(JObjectBase)>:type;Storagestorage_;;template<typenameRepr>voidReprStorage<Repr>:set(JniType<Repr>obj)noexceptnew(&storage_)Repr;ReprAccess<Repr>:set(get(),obj);template<typenameRepr>Repr&ReprStorage<Repr>:get()noexceptreturn*reinterpret_cast<Repr*>(&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*第L_:IGa>eCla»0lCu9l0fhJB¥aCl»i,mewrapperclass繼承關(guān)系JObjectBaseJObjectBase是wrapperclass的根父類,這里顯然存在一個問題:為何能用父類size的內(nèi)存空間去存放任意子類對象?完成繼承關(guān)系的討論后,再回顧這個問題。圖中的CustomJavaClass是一個自定義wrapperclass,它繼承于JavaClass的一個模板實例。所有Java類(除去Object類)的native鏡彳wwrapperclass,均需要繼承于JavaClass的某個模板實例。JavaClass起到兩個橋梁作用:當前定義的wrapperclass與對應(yīng)Java類父類的wrapperclass之間繼承關(guān)系的橋梁;當前定義的wrapperclass與對應(yīng)Java對象的JNIjobject的橋梁。它有三個模板參數(shù),下面是它的類聲明,其代碼位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h:template<typenameT,typenameBase=JObject,typenameJType=void>classFBEXPORTJavaClass:publicBasepublic:staticalias_ref<JClass>javaClassStatic();staticlocal_ref<JClass>javaClassLocal();protected:/Allocatesanewobjectandinvokesthespecifiedconstructor/LikeJClass'sgetConstructor,thisfunctioncanonlycheckatruntimeif/theclassactuallyhasaconstructorthatacceptsthecorrespondingtypes./WhileaJavaClass-typecanexposethisfunctiondirectly,itisrecommended/toinsteadtousethistoexplicitlyonlyexposethoseconstructorsthat/theJavaclassactuallyhas(i.e.withstaticcreate()functions).template<typename.Args>staticlocal_ref<T>newInstance(Args.args)returndetail:newInstance<T>(args.);javaobjectself()constnoexcept;無關(guān)的代碼已被略去。第一個模板參數(shù)是子wrapperclass的類型。JavaClass的這個模板實例作為這個wrapperclass的父類,提供了創(chuàng)建wrapperclass對象的工廠方法和與對應(yīng)jobject關(guān)聯(lián)的能力,故需要獲得子類的類型。第二個模板參數(shù)是該JavaClass模板實例的父類。它的默認類型是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)建了繼承鏈,wrapperclass具備了提供父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<JString,JObject,jstring>另外一種情況就是非預定義類型,也就是jobject這個通用類型(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成員變量,才能與根父類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/include/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;typedef_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類型如下:template<typenameT,typenameBase=JObject,typenameJType=void>classFBEXPORTJavaClass:publicBaseusingJObjType=typenamedetail:JTypeFor<T,Base,JType>public:using_javaobject=typenameJObjType:_javaobject;usingjavaobject=typenameJObjType:javaobject;namespacedetailtemplate<typename,typenameBase,typenameJType>structJTypeForstatic_assert(std:is_base_of<std:remove_pointer<jobject>:type,typenamestd:remove_pointer<JType>:type>:value,"");using_javaobject=typenamestd:remove_pointer<JType>:type;usingjavaobject=JType;template<typenameT,typenameBase>structJTypeFor<T,Base,void>/JNIpatternforjobjectassignablepointerstruct_javaobject:Base:_javaobject/Thisallowsustomapbacktothedefiningtype(inReprType,for/ple).typedefTJniRefRepr;usingjavaobject=_javaobject*;在JavaClass中,將jobject拓展定義為javaobject°javaobject是typenameJObjType:javaobject,也就是JTypeFor的一個模板實例類型的成員指針類型。以例子代碼中的MyClass為例,父類JavaClass接收的三個模板參數(shù)分別為MyClass,JObject,void,JTypeFor的三個模板參數(shù)也依次是它們,由于第三個參數(shù)是void,故會使用上面代碼中的JTypeForstructJTypeFor<MyClass,JObject,void>struct_javaobject:JObject:_javaobjecttypedefMyClassJniRefRepr;usingjavaobject=_javaobject*;可看到_javaobject繼承于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)存對象,而成員類型是屬于類定義,不會占用對象的空間。另,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),達到了有機的統(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,eitherajobject-liketypeoraJavaClass-derivedtype,ReprType<T>/isthecorrespondingJavaClass-derivedtypeandJniType<T>isthe/jobject-liketype.template<typenameT>usingReprType=typenamedetail:RefReprType<T>:type;template<typenameT>usingJniType=typenamedetail:JavaObjectType<T>:type;ReprType用來從模板參數(shù)中獲得wrapperclass類型,JniType用來從模板參數(shù)中獲得javaobject類型。通過這樣的機制,兩個類型彼此打通,故無論傳遞何種模板參數(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對象上,代碼如下:template<typenameT,typenameAlloc>inlineautobasic_strong_ref<T,Alloc>:operator->()noexcept->Repr*return&storage_.get();template<typenameT,typenameAlloc>inlineautobasic_strong_ref<T,Alloc>: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的生命周期管理。

注意事項

本文(ReactNative4Android源碼分析二JNI智能指針模板)為本站會員(新****)主動上傳,裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。 若此文所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng)(點擊聯(lián)系客服),我們立即給予刪除!

溫馨提示:如果因為網(wǎng)速或其他原因下載失敗請重新下載,重復下載不扣分。




關(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),我們立即給予刪除!