ReactNative4Android源碼分析二JNI智能指針模板
《ReactNative4Android源碼分析二JNI智能指針模板》由會(huì)員分享,可在線閱讀,更多相關(guān)《ReactNative4Android源碼分析二JNI智能指針模板(9頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、ReactNative4Android源碼分析二:JNI 智能指針 《JNI智能指針之介紹篇》: JNI指針 通常的app中,JNI提供的native函數(shù)主要充當(dāng)Java類的擴(kuò)展,邏輯層在Java端,JNI端較少使用OOP的設(shè)計(jì)思想。而對(duì)于native端功能較重的模塊,例如開(kāi)源的閱讀器FBReader, native端與Java端有較多交互,即native會(huì)主動(dòng)創(chuàng)建Java對(duì)象并調(diào)用它們的方法以實(shí)現(xiàn)功 能,這時(shí)就需要考慮將native至Java的操作與訪問(wèn)框架化,形成更高層次的封裝,以避免 直接使用原始的JNI反射API集去操作Java對(duì)象。 對(duì)于ReactNativeForA
2、ndroid而言,這套訪問(wèn)框架尤其重要,其核心就是JNI智能指針這個(gè) 基本數(shù)據(jù)類型。它的實(shí)現(xiàn)基于C11標(biāo)準(zhǔn),將先用幾篇對(duì)這套native至Java的操作框架進(jìn)行 介紹,為后續(xù)分析打下良好基礎(chǔ)。 Native引用 首先回顧一下JavaObject(jobject)在native端的三種引用類型: 全局引用 類似于C語(yǔ)言中的全局變量。使用NewGlobalRef創(chuàng)建,支持跨線程訪問(wèn),在調(diào)用釋放DeleteGlobalRef銷毀前,GC無(wú)法回收該引用對(duì)應(yīng)的javaobject。 局部引用 概念上與C語(yǔ)言中的局部變量有相似點(diǎn),但不等同。使用NewLocalRef創(chuàng)建,只能在本線程 內(nèi)
3、安全訪問(wèn),當(dāng)創(chuàng)建該引用的native調(diào)用鏈返回至JVM時(shí),未銷毀的局部引用會(huì)被JVM自 動(dòng)GC回收。但由于局部引用表容量有限,在返回至JVM前,可以調(diào)用DeleteLocalRef先 行銷毀,避免局部引用表超限引起崩潰。 弱全局引用 與全局引用一樣具有全局作用域,但不會(huì)影響GC回收,GC可以隨時(shí)回收該引用對(duì)應(yīng)的java object。使用NewWeakGlobalRef創(chuàng)建,當(dāng)需要使用時(shí),需要將其升級(jí)為全局引用或者局部 引用,若已被回收,會(huì)返回null,使用DeleteWeakGlobalRef銷毀。該引用類型使用場(chǎng)景較 少。 由上可見(jiàn),JNI智能指針的第一個(gè)需求,就是要自動(dòng)管
4、理jobject的生命周期,當(dāng)進(jìn)入與離開(kāi) 對(duì)應(yīng)作用域時(shí),需要自動(dòng)調(diào)用對(duì)應(yīng)生命周期的創(chuàng)建與銷毀函數(shù)。這在C++中,通常會(huì)結(jié)合構(gòu) 造與析構(gòu)函數(shù)來(lái)進(jìn)行配對(duì)調(diào)用。若功能僅限于此,就與普通的智能指針和mutext鎖管理機(jī) 制類似了,更重要的需求是在C++層提供與被管理的Java對(duì)象鏡像結(jié)構(gòu)的C++對(duì)象,形成高 層次封裝。這樣,對(duì)jobject的訪問(wèn)與操作就會(huì)被封裝在對(duì)應(yīng)的鏡像C++對(duì)象中,相關(guān)JNI 反射調(diào)用的細(xì)節(jié)被隱藏,對(duì)于其他native模塊而言,與Java層的交互被轉(zhuǎn)化成了與這些鏡 像C++對(duì)象的交互,整個(gè)實(shí)現(xiàn)風(fēng)格OOP化了。這些鏡像C++對(duì)象被稱為wrapper對(duì)象,其 定義代碼位
5、于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h文件中。
先看一個(gè)使用范例:
structMyClass:publicJavaClass
6、cal_ref
7、s獲取具體wrapper的類型。 給static成員變量kJavaDescriptor賦值為對(duì)應(yīng)Java類的全類名。 在wrapper類實(shí)現(xiàn)鏡像方法foo(),其會(huì)獲取jclass的包裝類JClass對(duì)象,并獲取jmethod的包裝類JMethod進(jìn)行調(diào)用。 create工廠方法中使用newInstance構(gòu)建鏡像對(duì)象的實(shí)例,并將其存至局部智能指針local_ref。 這樣就可以通過(guò)智能指針訪問(wèn)wrapperclass提供的foo方法,實(shí)現(xiàn)了native至Java的鏡像映射。 除了實(shí)現(xiàn)對(duì)一個(gè)java類的的映射,還需要支持對(duì)java繼承關(guān)系的映射。若java的MyClass 有一子類
8、MyChildClass,native層為其建立的wrapperclass可如下:
structMyChildClass:publicJavaClass
9、用是什么? 結(jié)尾 這些問(wèn)題將在下一篇智能指針的具體實(shí)現(xiàn)篇中解答。 總結(jié)一下,在ReactNativeforAndroid中,為了簡(jiǎn)化native層又Java層的調(diào)用,提供了鏡像結(jié)構(gòu)的wrapperclass,結(jié)合智能指針,將jobject的生命周期管理、javamethod的反射調(diào)用等“樣板”代碼封裝起來(lái),是比較優(yōu)雅的JNI調(diào)用框架。 《JNI智能指針之實(shí)現(xiàn)篇》 global_ref 全局指針與jobject全局引用相對(duì)應(yīng),使用場(chǎng)景包括全局變量、成員變量等。這些場(chǎng)景中的 jobject,不應(yīng)該從native返回至JVM時(shí)釋放,故使用global_ref進(jìn)行包裹。 local_r
10、ef 局部指針與jobject局部引用相對(duì)應(yīng),使用場(chǎng)景包括局部變量、函數(shù)返回值等。當(dāng)local_ref 離開(kāi)所在作用域時(shí),會(huì)釋放自身對(duì)jobject的引用,即在析構(gòu)函數(shù)中調(diào)用DeleteLocalRef。 weak_ref 弱指針與jobject弱全局引用相對(duì)應(yīng),在目前版本的RN代碼中未實(shí)際使用。 alias_ref 別名指針,不對(duì)持有的jobject進(jìn)行生命周期管理。即在構(gòu)造與析構(gòu)別名智能指針對(duì)象時(shí), 不會(huì)對(duì)持有的jobject進(jìn)行創(chuàng)建與銷毀的JNI操作。該指針的目的只是為了提供調(diào)用wrapper對(duì)象方法的能力,jobject的生命周期由另外的智能指針或直接由JVM進(jìn)行管理和保
11、證有效性,指針自身不對(duì)其額外進(jìn)行管理。 以上智能指針均未提供引用計(jì)數(shù)功能,而是通過(guò)在智能指針間交換被管理的對(duì)象來(lái)進(jìn)行指針 轉(zhuǎn)換。智能指針的類圖如下,其代碼位于 ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/References.h 智能指針類圖 智能指針 從上圖可以看出,由于功能區(qū)別,alias_ref別名指針是獨(dú)立的一個(gè)類,其余的智能指針有共 同的父類base_owned_ref。最需要關(guān)注智能指針的存儲(chǔ),base_owned_ref與alias_ref均有同 樣的成員變量: det
12、ail::ReprStoragestorage_;
**storage**_用來(lái)存儲(chǔ)創(chuàng)建出來(lái)的wrapper對(duì)象。這邊的設(shè)計(jì)比較巧妙,使用C++中的類型萃取技術(shù)(typetraits)把wrapper對(duì)象和jobject關(guān)聯(lián),并將jobject(JNI層),javaobject(RN層),wrapper對(duì)象(RN層)三者在內(nèi)存空間上統(tǒng)一了。先看ReprStorage的實(shí)現(xiàn):template 13、r>obj)noexcept;
Repr&get()noexcept;
constRepr&get()constnoexcept;
JniType 14、r>obj)noexcept{
new(&storage_)Repr;
ReprAccess 15、ge_內(nèi)存空間的指針通過(guò)reinterpret_cast類型轉(zhuǎn)換為Repr類型。ReprStorage的模板參數(shù)Repr是存儲(chǔ)的wrapperclass的類型,在上章的使用范例中,也就是MyClass:
structMyClass:publicJavaClasswrapperclass之間的繼承關(guān)系如下:
,明峋:西M
.I?:
I__Jd*第L_:I
Ga>eCla?0lCu9l0fhJB¥aCl?i,
me
wrapperclass繼承關(guān)系
JObjectBase
JObjectBase是wrapperclass的根父類,這里顯然存在一個(gè)問(wèn)題:為何能用父類size的內(nèi) 16、存
空間去存放任意子類對(duì)象?完成繼承關(guān)系的討論后,再回顧這個(gè)問(wèn)題。圖中的CustomJavaClass是一個(gè)自定義wrapperclass,它繼承于JavaClass的一個(gè)模板實(shí)例。所有Java類(除去Object類)的native鏡彳wwrapperclass,均需要繼承于JavaClass的某個(gè)模板實(shí)例。JavaClass起到兩個(gè)橋梁作用:當(dāng)前定義的wrapperclass與對(duì)應(yīng)Java類父類的wrapperclass
之間繼承關(guān)系的橋梁;當(dāng)前定義的wrapperclass與對(duì)應(yīng)Java對(duì)象的JNIjobject的橋梁。它
有三個(gè)模板參數(shù),下面是它的類聲明,其代碼位于
ReactA 17、ndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h:template 18、sthespecifiedconstructor
///LikeJClass'sgetConstructor,thisfunctioncanonlycheckatruntimeif
///theclassactuallyhasaconstructorthatacceptsthecorrespondingtypes.
///WhileaJavaClass-typecanexposethisfunctiondirectly,itisrecommended
///toinsteadtousethistoexplicitlyonlyexposethoseconstructorsthat
// 19、/theJavaclassactuallyhas(i.e.withstaticcreate()functions).
template 20、ss對(duì)象的
工廠方法和與對(duì)應(yīng)jobject關(guān)聯(lián)的能力,故需要獲得子類的類型。
第二個(gè)模板參數(shù)是該JavaClass模板實(shí)例的父類。
它的默認(rèn)類型是JObject,代表java.lang.Object類的wrapperclass,是唯一不需要繼承于
JavaClass的wrapper對(duì)象。JObject提供了對(duì)java對(duì)象的Class、Field、Method等的訪問(wèn)封裝方法,wrapperclass通過(guò)對(duì)它的繼承關(guān)系,獲得了去調(diào)用Javamethod的能力。若wrapperclass無(wú)需提供Java類父類方法的調(diào)用能力,則第二個(gè)模板參數(shù)保持默認(rèn)值JObject即可,否
則,第二個(gè)模板 21、參數(shù)就為Java類父類的wrapperclass,例子在上章中已提供。由于JavaClass幫助構(gòu)建了繼承鏈,wrapperclass具備了提供父java類的native鏡像方法的能力。
第三個(gè)模板參數(shù)是定義的wrapperclass對(duì)應(yīng)Java對(duì)象的JNIjobject的類型
JavaClass會(huì)將wrapperclass與jobject建立起綁定關(guān)系。根據(jù)jobject的具體類型,會(huì)分兩種情況,如果為JNI預(yù)定義的jobject類型,例如jclass、jthrowable、jarray、jstring等,第三個(gè)
模板參數(shù)就是它們,RN中已經(jīng)預(yù)定義了它們的wrapperclass。例如 22、:
classFBEXPORTJString:publicJavaClass 23、ObjectBase一
樣。而對(duì)于一個(gè)C++類而言,對(duì)象的size就是所有非static成員變量的size之和(需考慮內(nèi)存對(duì)齊),這就約束了wrapperclass作為子類不能額外聲明任何非static成員變量,才能與
根父類JObjectBase保持size的一致。從wrapperclass的設(shè)計(jì)目的考慮,它只是Java類在native空間的鏡像類和接口包裝類,業(yè)務(wù)邏輯應(yīng)由調(diào)用者實(shí)現(xiàn),wrapperclass自身應(yīng)該是無(wú)狀態(tài)的,
所以不允許wrapperclass定義非static成員變量是合理的。
智能指針存儲(chǔ)的是wrapperclass的實(shí)例,wrapperclass中存儲(chǔ)的是j 24、object,從以上分析可以
知道,存儲(chǔ)的jobject成員變量只能由根父類JObjectBase去承載。下面是JObjectBase的類
定義,代碼位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/References-forward.h:
structJObjectBase{
jobjectget()constnoexcept;
voidset(jobjectreference)noexcept;
jobjectthis_;
};
JObjectBase是一個(gè)簡(jiǎn)單的bean類,唯一的成員變量就是jobje 25、ct,這也是所有wrapperclass
唯一的成員變量。在JavaClass模板類中,為了實(shí)現(xiàn)jobject與wrapperclass兩者的關(guān)聯(lián),對(duì)
jobject做了內(nèi)部擴(kuò)展定義。為了理解它,先回顧下jobject在jni.h中的原始定義:
class_jobject{};
typedef_jobject*jobject;
class_jstring:public_jobject{};
所以,jobject就是個(gè)指針,指向javaobject在JVM中的內(nèi)存對(duì)象,對(duì)于像**dexposed**這
樣的熱修復(fù)框架,就是利用這些指針去修改java對(duì)象模型來(lái)改變javamethod 26、的屬性以實(shí)現(xiàn)
hook。這里的定義_jobject是空類,只是為了定義指針語(yǔ)法以在JNI中去引用內(nèi)存對(duì)象,并
不意味Java內(nèi)存對(duì)象真的是個(gè)空對(duì)象,真正定義是JVM內(nèi)部的、平臺(tái)相關(guān)的,而不需要將
實(shí)現(xiàn)細(xì)節(jié)暴露給JNI。在JavaClass中,對(duì)jobject的擴(kuò)展定義javaobject類型如下:
template 27、pe>;
public:
using_javaobject=typenameJObjType::_javaobject;
usingjavaobject=typenameJObjType::javaobject;
};
namespacedetail{
template 28、>::value,"");
using_javaobject=typenamestd::remove_pointer 29、).
typedefTJniRefRepr;
};
usingjavaobject=_javaobject*;};
}
在JavaClass中,將jobject拓展定義為javaobject°javaobject是typenameJObjType::javaobject,也就是JTypeFor的一個(gè)模板實(shí)例類型的成員指針類型。以例子代碼中的MyClass為例,父類JavaClass接收的三個(gè)模板參數(shù)分別為MyClass,JObject,void,JTypeFor的三個(gè)模板參數(shù)也依次是它們,由于第三個(gè)參數(shù)是void,故會(huì)使用上面代碼中的JTypeFor
structJTypeFor< 30、MyClass,JObject,void>{struct_javaobject:JObject::_javaobject{typedefMyClassJniRefRepr;
};
usingjavaobject=_javaobject*;};
}
可看到_javaobject繼承于JObject::_javaobject,它的定義如下:
typedef_jobject_javaobject;typedef_javaobject*javaobject;
JObject::_javaobject就是jni.h中的」object類型,故MyClass中的」avaobject又^_jobj 31、ect的繼承擴(kuò)展,只是添加了一個(gè)嵌套類成員類型JniRefRepr,來(lái)指向當(dāng)前_javaobject所對(duì)應(yīng)的
wrapperclass類型,這就是所謂的C++類型萃取技術(shù)。因?yàn)開(kāi)jobject是用來(lái)指向Java內(nèi)存對(duì)
象,所以不能用繼承后添加成員變量的方式來(lái)擴(kuò)展,否則會(huì)破壞內(nèi)存對(duì)象,而成員類型是屬于類定義,不會(huì)占用對(duì)象的空間。另,javaobject是指向_javaobject的指針,jobject是指向_jobject的指針。
問(wèn)題解答
現(xiàn)在來(lái)解答上章的三個(gè)問(wèn)題
javaobject與jobject的關(guān)系是什么?
兩者本質(zhì)是一樣的,都是指向java內(nèi)存對(duì)象的JNI引用;區(qū)別是ja 32、vaobject是jobject繼承擴(kuò)展,繼承后的javaobject擁有一個(gè)類成員類型變量,指向?qū)?yīng)的wrapperclass,使得兩者彼
此關(guān)聯(lián)。從內(nèi)存上看,sizeof(JObjectBase)==sizeof(任意wrapperclass)==sizeof(jobject)==sizeof(javaobject),達(dá)到了有機(jī)的統(tǒng)一。
為什么智能指針的模板參數(shù)能夠接受多種類型?
在上章例子中,與傳遞了不同模板參數(shù),從語(yǔ)法上看區(qū)別很大,但在內(nèi)部
實(shí)現(xiàn)時(shí),都會(huì)進(jìn)行類型萃取。即無(wú)論傳遞的何種類型,都會(huì)萃取出對(duì)應(yīng)的ReprType(wrapperclass類型)、JniType(java 33、object類型)。javaobject類是wrapperclass的成員類型,故從wrapperclass可以獲得對(duì)應(yīng)javaobject引用的類型;javaobject類的成員類型是wrapperclass,故從javaobject業(yè)可以獲得對(duì)應(yīng)wrapperclass的類型。在框架中提供了兩個(gè)工具來(lái)進(jìn)行類型萃取
和轉(zhuǎn)換:
//GivenT,eitherajobject-liketypeoraJavaClass-derivedtype,ReprType 34、bject-liketype.
template 35、作用是什么?
從上可以了解到,智能指針的模板參數(shù)用來(lái)獲取存儲(chǔ)的wrapperclass的類型。對(duì)于local_ref
和global_ref,它們由于都是強(qiáng)引用,可以用來(lái)直接調(diào)用存儲(chǔ)的wrapperclass提供的方法,
所以它們的實(shí)現(xiàn)模板類basic_strong_ref在base_owned_ref提供的存儲(chǔ)功能的基礎(chǔ)上,繼承
擴(kuò)展提供了指針操作符的重載,以將對(duì)智能指針的訪問(wèn)轉(zhuǎn)發(fā)到wrapper對(duì)象上,代碼如下:
template 36、noexcept->Repr*{return&storage_.get();
}template
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 市教育局冬季運(yùn)動(dòng)會(huì)安全工作預(yù)案
- 2024年秋季《思想道德與法治》大作業(yè)及答案3套試卷
- 2024年教師年度考核表個(gè)人工作總結(jié)(可編輯)
- 2024年xx村兩委涉案資金退還保證書
- 2024年憲法宣傳周活動(dòng)總結(jié)+在機(jī)關(guān)“弘揚(yáng)憲法精神推動(dòng)發(fā)改工作高質(zhì)量發(fā)展”專題宣講報(bào)告會(huì)上的講話
- 2024年XX村合作社年報(bào)總結(jié)
- 2024-2025年秋季第一學(xué)期初中歷史上冊(cè)教研組工作總結(jié)
- 2024年小學(xué)高級(jí)教師年終工作總結(jié)匯報(bào)
- 2024-2025年秋季第一學(xué)期初中物理上冊(cè)教研組工作總結(jié)
- 2024年xx鎮(zhèn)交通年度總結(jié)
- 2024-2025年秋季第一學(xué)期小學(xué)語(yǔ)文教師工作總結(jié)
- 2024年XX村陳規(guī)陋習(xí)整治報(bào)告
- 2025年學(xué)校元旦迎新盛典活動(dòng)策劃方案
- 2024年學(xué)校周邊安全隱患自查報(bào)告
- 2024年XX鎮(zhèn)農(nóng)村規(guī)劃管控述職報(bào)告