http://liumspace.spaces.live.com/blog/cns!bc24129fc2e42afd!122.entry
JavaXPCOM
JavaXPCOM基于一套與Eclipse
SWT不同的思路。在JavaXPCOM中,每一個(gè)XPCOM interface有一個(gè)對(duì)應(yīng)的Java interface,注意這里是Java
interface,而不是Java class。那么,在JavaXPCOM中怎么生成一個(gè)XPCOM對(duì)象的Java
wrapper呢?在JavaXPCOM中,巧妙地使用了reflection。對(duì)每一個(gè)XPCOM對(duì)象,會(huì)生成一個(gè)
Proxy 來(lái)作為Java wrapper,這個(gè)Proxy對(duì)象實(shí)現(xiàn)XPCOM對(duì)象所實(shí)現(xiàn)的interface。然后這個(gè)Proxy把Java interface中的方法調(diào)用再delegate到一個(gè)JavaXPCOM提供的
XPCOMJavaProxy(實(shí)現(xiàn)
InvocationHandler)上。
這
里有幾個(gè)問(wèn)題:1。系統(tǒng)根據(jù)一個(gè)XPCOM對(duì)象的指針,怎么知道這個(gè)XPCOM對(duì)象實(shí)現(xiàn)了什么XPCOM接口?再怎么根據(jù)這個(gè)XPCOM接口找到對(duì)應(yīng)的
Java interface來(lái)生成Proxy?2。XPCOMJavaProxy怎么把一個(gè)Java調(diào)用再映射到底層的XPCOM調(diào)用上?
JavaXPCOM是這樣實(shí)現(xiàn)的:
- 對(duì)每一個(gè)XPCOM對(duì)象的指針,知道其實(shí)現(xiàn)的interface的IID。
- 使用nsIInterfaceInfoManager來(lái)reflect 這個(gè)IID,得到這個(gè)interface的meta data(nsIInterfaceInfo)
- 將這個(gè)XPCOM對(duì)象的指針及nsIInterfaceInfo組合在一起,放在一個(gè)JavaXPCOMInterface的數(shù)據(jù)結(jié)構(gòu)里。
- 用這個(gè)JavaXPCOMInterface結(jié)構(gòu)的指針來(lái)構(gòu)建XPCOMJavaProxy(java
wrapper)。構(gòu)建XPCOMJavaProxy對(duì)象時(shí)(XPCOMJavaProxy#createProxy(Class
aInterface, long aXPCOMInterface))有兩個(gè)參數(shù),第一個(gè)為這個(gè)proxy實(shí)現(xiàn)的Java
interface。這個(gè)Java interface的名字由"org.mozilla.xpcom" + (XPCOM interface
name)得來(lái)。
- 當(dāng)XPCOMJavaProxy上的方法被調(diào)用時(shí),native
code會(huì)得到方法名、參數(shù)數(shù)組以及JavaXPCOMInterface的指針。從JavaXPCOMInterface可以得到
nsIInterfaceInfo,通過(guò)nsIInterface里所包含的meta data,可以得到這個(gè)方法在virtual
table中的位置。同時(shí)meta
data還會(huì)包含信息說(shuō)明每個(gè)參數(shù)的數(shù)據(jù)類型,根據(jù)這個(gè)信息,可以把每個(gè)參數(shù)marshall成一個(gè)nsXPTCVariant結(jié)構(gòu)。
- 通過(guò)xptcall,就可以完成對(duì)virtual table中的方法的調(diào)用。
- 對(duì)方法調(diào)用的結(jié)果,可以再根據(jù)meta
data來(lái)unmarshall成Java對(duì)象。如果某個(gè)out參數(shù)或return參數(shù)是一個(gè)XPCOM對(duì)象,在meta
data中會(huì)描述這個(gè)參數(shù)的interface的IID,那么又可以象第一步一樣來(lái)對(duì)其生成Java wrapper(XPCOMJavaProxy)(nsJavaXPCOMBindingUtils.cpp#GetNewOrUsedJavaObject)。
當(dāng)然,實(shí)際的實(shí)現(xiàn)更復(fù)雜,比如說(shuō)有一個(gè)global table來(lái)記錄Java wrapper與native的JavaXPCOMInterface之間的關(guān)系以避免不必要的多次為同一XPCOM對(duì)象建立Java wrapper等。
在Java中實(shí)現(xiàn)COM/XPCOM組件(component)
前面討論了怎么從Java中調(diào)用COM/XPCOM中的組件,接下來(lái)討論怎么用Java語(yǔ)言來(lái)實(shí)現(xiàn)COM/XPCOM組件。
JavaXPCOM
?JavaXPCOM中的支持還是依賴了type
information,這是有了這個(gè)依賴,JavaXPCOM中實(shí)現(xiàn)XPCOM組件要容易得多。在JavaXPCOM中,只需要這個(gè)Java對(duì)象實(shí)現(xiàn)了
所需要實(shí)現(xiàn)的XPCOM interface所對(duì)應(yīng)的Java interface即可。
- 當(dāng)一個(gè)Java object作為參數(shù)傳給某個(gè)XPCOM方法時(shí),native code會(huì)通過(guò)這個(gè)方法的meta data,知道這個(gè)參數(shù)應(yīng)該是一個(gè)XPCOM對(duì)象。
- native code會(huì)檢查這個(gè)Java object是不是一個(gè)Java wrapper,如果是,那么可以直接從這個(gè)Java wrapper知道它所wrap的XPCOM對(duì)象。
- 接下來(lái)會(huì)檢查是不是已經(jīng)給這個(gè)Java object生成過(guò)stub,如果沒(méi)有則生成一個(gè)nsJavaXPTCStub。nsJavaXPTCStub
會(huì)根據(jù)meta data生成virtual table,而且當(dāng)virtual table中的方法被調(diào)用時(shí),會(huì)根據(jù)meta
data知道被調(diào)用方法的名字,再根據(jù)這個(gè)名字到Java object中通過(guò)reflect找到對(duì)應(yīng)的Java方法并調(diào)用它。
另外JavaXPCOM的實(shí)現(xiàn)中還實(shí)現(xiàn)了reference management,這樣在Java code中不再需要去實(shí)現(xiàn)如AddRef/Release,系統(tǒng)已經(jīng)都管理好了。
JavaXPCOM
優(yōu)點(diǎn):
- 每個(gè)XPCOM interface對(duì)應(yīng)到Java中還是interface。
- 支持Java的garbase collection。在XPCOMJavaProxy中,重載了finalize()方法,所以Java programmer不需要再去調(diào)用Release。
- 增加新的XPCOM interface容易。只需在org.mozilla.xpcom這個(gè)package中增加相應(yīng)的Java interface即可。
- Java interface可以通過(guò)工具自動(dòng)生成。
- 用Java實(shí)現(xiàn)XPCOM組件非常簡(jiǎn)單。
缺點(diǎn):
- 由于實(shí)現(xiàn)依賴nsIInterfaceInfoManager,也就依賴typelib。這樣一來(lái),方法調(diào)用不能象Eclipse SWT中一樣直接轉(zhuǎn)換為virtual table調(diào)用,效率要明顯低一些。另外,只能支持那些支持typelib的interface。
- 雖然增加新的XPCOM interface容易,但這個(gè)interface必須放在org.mozilla.xpcom這個(gè)package中,不適合第三方擴(kuò)充。