笨笔老刘's profile笨笔老刘BlogLists Tools Help

Blog


    March 06

    比较Eclipse与Mozilla中的COM/XPCOM Java Wrapper技术

     

    背景

    Microsoft 的COM是在Microsoft平台上广泛使用的一项技术,它是建立可重用的构件 (component)的基础。Mozilla的 XPCOM是由Mozilla.org实现,它类似COM,跨平台,是Mozilla用来建造如Mozilla FirefoxMozilla Thundermail等应用程序的基础。
     
    COM和XPCOM都是基于virtual table技术,是一种二进制的规范(在Windows平台上,XPCOM与COM做到了二进制兼容。所以Windows平台上的XPCOM控件同时也是 COM控件)。COM和XPCOM的规范本身都没有限制实现的语言,但由于C++的virtual table与COM/XPCOM的virtual table在二进制上兼容,所以C++成了COM/XPCOM世界中的首选语言。
     
    Java是受控语言,对其我们无法控制其在物理内存中的各种数据结构的位置,更谈不上控制virtual table的结构了。所以要支持Java与COM/XPCOM的交互,需要有C++写的native code来帮助。这里想比较一下两个支持Java/COM/XPCOM互操作的典型例子:Eclipse的SWT中对COM的支持,和Mozilla 的XULRunner中的JavaXPCOM
     

    基本COM/XPCOM支持

    在Java中调用COM/XPCOM

    Eclipse SWT

    在Eclipse SWT中,每个需要被调用的COM接口会有一个对应的Java class。所有这些Java class组成与COM interface同样的继承结构,它们都继承自org.eclipse.swt.internal.ole.win32.IUnknown这个class,对应COM中的IUnknown。IUnknown中会纪录一个field:address,对应COM对象的指针。
     
    对每一个COM interface中的方法,在其对应的Java class中会有一个同名的方法,接收Java参数,大部分情况下,这个Java方法会直接调用一个native方法: org.eclipse.swt.internal.ole.win32.COM#VtblCall(...)。因为不同COM interface的不同的方法可能有不同的个数和类型的参数,所以在org.eclipse.swt.internal.ole.win32.COM中提供一组VtblCall(...)的实现,每一个接受不同个数和类型的参数。每个VtblCall方法的实现基本是一样的,因为在这个方法中的参数包括了底层COM对象的地址,以及方法在virtual table中的序号,所以这个方法只需把Java的参数组marshall成C++参数,然后用virtual table来调用即可。

    public class IUnknown
    {
        int address;
    public IUnknown(int address) {
        this.address = address;
    }
    public int AddRef() {
        return COM.VtblCall(1, address);
    }
    public int getAddress() {
        return address;
    }
    public int QueryInterface(GUID riid, int ppvObject[]) {
        return COM.VtblCall(0, address, riid, ppvObject);
    }
    public int Release() {
        return COM.VtblCall(2, address);
    }
    }


    JavaXPCOM

    JavaXPCOM基于一套与Eclipse SWT不同的思路。在JavaXPCOM中,每一个XPCOM interface有一个对应的Java interface,注意这里是Java interface,而不是Java class。那么,在JavaXPCOM中怎么生成一个XPCOM对象的Java wrapper呢?在JavaXPCOM中,巧妙地使用了reflection。对每一个XPCOM对象,会生成一个Proxy 来作为Java wrapper,这个Proxy对象实现XPCOM对象所实现的interface。然后这个Proxy把Java interface中的方法调用再delegate到一个JavaXPCOM提供的XPCOMJavaProxy(实现InvocationHandler)上。

    这里有几个问题:1。系统根据一个XPCOM对象的指针,怎么知道这个XPCOM对象实现了什么XPCOM接口?再怎么根据这个XPCOM接口找到对应的 Java interface来生成Proxy?2。XPCOMJavaProxy怎么把一个Java调用再映射到底层的XPCOM调用上?

    JavaXPCOM是这样实现的:
    1. 对每一个XPCOM对象的指针,知道其实现的interface的IID。
    2. 使用nsIInterfaceInfoManager来reflect 这个IID,得到这个interface的meta data(nsIInterfaceInfo
    3. 将这个XPCOM对象的指针及nsIInterfaceInfo组合在一起,放在一个JavaXPCOMInterface的数据结构里。
    4. 用这个JavaXPCOMInterface结构的指针来构建XPCOMJavaProxy(java wrapper)。构建XPCOMJavaProxy对象时(XPCOMJavaProxy#createProxy(Class aInterface, long aXPCOMInterface))有两个参数,第一个为这个proxy实现的Java interface。这个Java interface的名字由"org.mozilla.xpcom" + (XPCOM interface name)得来。
    5. 当XPCOMJavaProxy上的方法被调用时,native code会得到方法名、参数数组以及JavaXPCOMInterface的指针。从JavaXPCOMInterface可以得到 nsIInterfaceInfo,通过nsIInterface里所包含的meta data,可以得到这个方法在virtual table中的位置。同时meta data还会包含信息说明每个参数的数据类型,根据这个信息,可以把每个参数marshall成一个nsXPTCVariant结构。
    6. 通过xptcall,就可以完成对virtual table中的方法的调用。
    7. 对方法调用的结果,可以再根据meta data来unmarshall成Java对象。如果某个out参数或return参数是一个XPCOM对象,在meta data中会描述这个参数的interface的IID,那么又可以象第一步一样来对其生成Java wrapper(XPCOMJavaProxy)(nsJavaXPCOMBindingUtils.cpp#GetNewOrUsedJavaObject)。
    当然,实际的实现更复杂,比如说有一个global table来记录Java wrapper与native的JavaXPCOMInterface之间的关系以避免不必要的多次为同一XPCOM对象建立Java wrapper等。

    在Java中实现COM/XPCOM组件(component)

    前面讨论了怎么从Java中调用COM/XPCOM中的组件,接下来讨论怎么用Java语言来实现COM/XPCOM组件。

    Eclipse SWT

     这里我尝试用一个图来说明Eclipse SWT中的实现。
    1. SWT会在内存中构建一个native function table(see COMObject#Callbacks)。这个table的横坐标为virtual table中的index,纵坐标为参数的个数。
    2. 这个table中的每个function的实现会调用COMObject这个类中的对应的静态方法:callbackn(int[] callbackArgs),这里的callbackn表示的是callback0,callback1...。在SWT中, org.eclipse.swt.internal.Callback这个类实现了一套通用的从native code回调Java的机制。COMObject使用了这套机制。
    3. 在传给callbackn(int[] callbackArgs)的参数中,第一个是virtual table的地址,根据这个地址,系统可以根据一个全局的hashtable找到对应的COMObject实例。然后调用 COMObject#methodn(int[] args)方法。这里methodn不是静态方法。
    4. 缺省的methodn的实现会返回COM.E_NOTIMPL。用户程序可以override,来实现自己的逻辑。
    5. 再回过头来看怎么在Java中实现一个COM组件:实例化一个COMObject,并override对应的methodn方法。作为参数传给COMObject的constructor每个methodn会需要几个参数。COMObject的初始化函数会在内存中构建virtual table,并让每个virtual table entry指向对应的在native function table中的位置(这里需要使用每个method需要几个参数这个信息)
    下面是一个例子,简单地在Java中实现了一个IUnknown
    iUnknown = new COMObject(new int[]{2, 0, 0}){ /* 2,0,0 is the arg count for queryInterface/addRef/release */
        int refCount = 0;
        public int method0(int[] args) {return QueryInterface(args[0], args[1]);}
        public int method1(int[] args) {return AddRef();}
        public int method2(int[] args) {return Release();}
        public int AddRef() { return ++refCount;}
        public int Release() {
            refCount--;
            if (refCount == 0) {COMObject.this.dispose();}
            return refCount;
        }
        protected int QueryInterface(int riid, int ppvObject) {
            if (riid == 0 || ppvObject == 0)
                return COM.E_NOINTERFACE;
            GUID guid = new GUID();
            COM.MoveMemory(guid, riid, GUID.sizeof);

            if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
                COM.MoveMemory(ppvObject, new int[] {iUnknown.getAddress()}, 4);
                AddRef();
                return COM.S_OK;
            }
            COM.MoveMemory(ppvObject, new int[] {0}, 4);
            return COM.E_NOINTERFACE;
        }
    };


    实现了多个COM interface的Java对象要稍微复杂一点。一般是在一个Java对象中管理多个COMObject,这几个COMObject的AddRef/Release/QueryInterface这几个函数的实现统一实现。

    JavaXPCOM

     JavaXPCOM中的支持还是依赖了type information,这是有了这个依赖,JavaXPCOM中实现XPCOM组件要容易得多。在JavaXPCOM中,只需要这个Java对象实现了所需要实现的XPCOM interface所对应的Java interface即可。
    1. 当一个Java object作为参数传给某个XPCOM方法时,native code会通过这个方法的meta data,知道这个参数应该是一个XPCOM对象。
    2. native code会检查这个Java object是不是一个Java wrapper,如果是,那么可以直接从这个Java wrapper知道它所wrap的XPCOM对象。
    3. 接下来会检查是不是已经给这个Java object生成过stub,如果没有则生成一个nsJavaXPTCStub。nsJavaXPTCStub 会根据meta data生成virtual table,而且当virtual table中的方法被调用时,会根据meta data知道被调用方法的名字,再根据这个名字到Java object中通过reflect找到对应的Java方法并调用它。
    另外JavaXPCOM的实现中还实现了reference management,这样在Java code中不再需要去实现如AddRef/Release,系统已经都管理好了。

    总结

    在这里我们比较了Eclipse SWT和JavaXPCOM中对基本COM/XPCOM的支持的基本原理。这里没有讨论更高级一些的应用,比如说scripting(automation)。

    Eclipse SWT

    优点:
    1. 结构简单。因为支持基于virtual table,所以支持几乎最底层的COM规范。高效。
    2. 可以用工具来自动生成新的COM interface的Java wrapper。因为每个Java wrapper class的结构基本一样。
    缺点:
    1. 不支持Java的garbage collection。Developer必须记得调用IUnknown#Release()方法,否则如果COM对象的Java wrapper被gc了,有可能造成内存泄露。
    2. 只支持有限种COM#VtblCall(...)方法。如果有一个新的COM interface中的某方法,需要更多的参数,而系统提供的COM#VtblCall(...)方法中没有与之匹配的,则需要另外再提供native code。
    3. 用Java实现XPCOM组件复杂。

    JavaXPCOM

    优点:
    1. 每个XPCOM interface对应到Java中还是interface。
    2. 支持Java的garbase collection。在XPCOMJavaProxy中,重载了finalize()方法,所以Java programmer不需要再去调用Release。
    3. 增加新的XPCOM interface容易。只需在org.mozilla.xpcom这个package中增加相应的Java interface即可。
    4. Java interface可以通过工具自动生成。
    5. 用Java实现XPCOM组件非常简单。
    缺点:
    1. 由于实现依赖nsIInterfaceInfoManager,也就依赖typelib。这样一来,方法调用不能象Eclipse SWT中一样直接转换为virtual table调用,效率要明显低一些。另外,只能支持那些支持typelib的interface。
    2. 虽然增加新的XPCOM interface容易,但这个interface必须放在org.mozilla.xpcom这个package中,不适合第三方扩充。

    Comments (6)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    No namewrote:
    <a href="http://hala.ew09.com">哈啦論壇</a>
    <a href="http://tw-myfish.blogspot.com/">洗米水的用處</a>
    <a href="http://blog.sina.com.tw/xiaocai14/">婚紗</a>
    <a href="http://blog.sina.com.tw/xiaocai15/">李敏鎬</a>
    <a href="http://blog.sina.com.tw/xiaocai16/">大樂透</a>
    <a href="http://blog.sina.com.tw/movie008/">地球很美有賴你</a>
    <a href="http://cvnfghn.blogspot.com/">守護甜心漫畫</a>
    <a href="http://bngngh.blogspot.com/">火影忍者疾風傳</a>
    <a href="http://dxvdfg.blogspot.com/">花漾明星</a>
    <a href="http://mhjhj.blogspot.com/">唱 k 小魚仙遊戲</a>
    <a href="http://hjyuf.blogspot.com/">衝鋒 21 動畫</a>
    <a href="http://ertyryty.blogspot.com/">涼宮春日的憂鬱</a>
    <a href="http://ghtht.blogspot.com/">寵物小精靈鑽石珍珠</a>
    <a href="http://tw-dger.blogspot.com/">海賊王漫畫連載</a>
    <a href="http://tw-ghjk.blogspot.com/">gundam 00 官網</a>
    <a href="http://tw-hala.blogspot.com/">黑執事 wallpaper</a>
    <a href="http://hala-ew09.blogspot.com/">寵物小精靈綠寶石</a>
    <a href="http://vala128.blogspot.com/">one piece 漫畫</a>
    <a href="http://linlong08.blogspot.com/">龍珠 z</a>
    <a href="http://apple128.blogspot.com/">數碼暴龍 online</a>
    <a href="http://xiaocai04.blogspot.com/">小女神花鈴</a>
    <a href="http://cheerychong02.blogspot.com/">keroro 軍曹</a>
    <a href="http://peng0219.blogspot.com/">多啦 a 夢</a>
    <a href="http://month05.blogspot.com/">花樣男子</a>
    <a href="http://tw-jingang.blogspot.com/">變形金剛</a>
    <a href="http://tw-meng.blogspot.com/">夢之音樂街</a>
    <a href="http://mybabyyyy.blogspot.com/">星座運勢</a>
    <a href="http://tw-fengzigu.blogspot.com/">楓之穀遊戲</a>
    <a href="http://tw-sweetheart.blogspot.com/">守護甜心漫畫</a>
    <a href="http://myccpl6.blogspot.com/">黃金價格</a>
    <a href="http://chongtom.blogspot.com/">瘦小腹魚湯</a>
    <a href="http://tw-idose.blogspot.com/">美甲</a>
    <a href="http://tw-idose.blogspot.com/">美甲課程</a>
    <a href="http://tw-poppysnail.blogspot.com/">yoga</a>
    <a href="http://tw-chienchilin.blogspot.com/">激光矯視</a>
    <a href="http://tw-berobot.blogspot.com/">整容</a>
    <a href="http://tw-shengnu.blogspot.com/">脫髮</a>
    <a href="http://tw-shengnu.blogspot.com/">治療脫髮</a>
    <a href="http://tw-shengnu.blogspot.com/">女性脫髮</a>
    <a href="http://tw-wuzhu.blogspot.com/">乳癌</a>
    <a href="http://tw-wuzhu.blogspot.com/">乳癌食療</a>
    <a href="http://tw-wuzhu.blogspot.com/">乳癌化療需知</a>
    <a href="http://tw-myfish.blogspot.com/">流感</a>
    <a href="http://tw-myfish.blogspot.com/">流感疫苗</a>
    <a href="http://tw-honghong.blogspot.com/">身體檢查</a>
    <a href="http://tw-honghong.blogspot.com/">女性身體檢查</a>
    <a href="http://tw-triangle.blogspot.com/">減肥</a>
    <a href="http://tw-triangle.blogspot.com/">減肥瘦身方法</a>
    <a href="http://tw-triangle.blogspot.com/">正確的減肥方法</a>
    <a href="http://tw-zhuoyouling.blogspot.com/">美白</a>
    <a href="http://tw-zhuoyouling.blogspot.com/">美白方法</a>
    <a href="http://tw-zhuoyouling.blogspot.com/">牙齒美白</a>
    <a href="http://tw-zhuoyouling.blogspot.com/">美白去斑</a>
    <a href="http://tw-zhuoyouling.blogspot.com/">美白面膜</a>
    <a href="http://tw-madoka.blogspot.com/">防曬</a>
    <a href="http://tw-madoka.blogspot.com/">不要防曬</a>
    <a href="http://tw-yan.blogspot.com/">愛滋病</a>
    <a href="http://tw-yan.blogspot.com/">愛滋病病徵</a>
    <a href="http://tw-yan.blogspot.com/">愛滋病測試</a>
    <a href="http://tw-mylove.blogspot.com/">大腸癌</a>
    <a href="http://tw-mylove.blogspot.com/">大腸癌病徵</a>
    <a href="http://tw-mylove.blogspot.com/">大腸癌的檢查方法</a>
    <a href="http://tw-jiajiwen.blogspot.com/">星座</a>
    <a href="http://tw-jiajiwen.blogspot.com/">星座運勢</a>
    <a href="http://tw-jiajiwen.blogspot.com/">雙子座</a>
    <a href="http://tw-jiajiwen.blogspot.com/">星座配對</a>
    <a href="http://tw-zhaoyayi.blogspot.com/">愛情測驗</a>
    <a href="http://tw-zhaoyayi.blogspot.com/">愛情測驗小遊戲</a>
    June 22
    Feb. 27
    Picture of Anonymous
    (没有名字) wrote:

    徵 信是個富有挑戰的工作,忙碌、刺激、激情。最后的結局總是有人哭,有人笑。在徵信社工作的幾年時間里,我感悟到很多生活的無奈與殘酷。閑暇時我去中古车市 场,感覺工作太緊張,放松一下而已,不是純粹的為了淘二手车。私家偵探也就是徵信工作人員似乎是個很酷的詞,但是如果誰需要私家偵探來幫忙的話,他(她) 的婚姻也許已經亮起了紅燈。每天陪著星際客戶喝著咖啡,似乎是一件很爽的事,可是她們的眼淚比咖啡要苦的多。常常聽他們說嘈雜的燈光音響麻痹著他們的神 經,讓他們過著醉生夢死的生活。其實,誰不渴望幸福美滿的愛情。沒有團體制服不了那些玩弄生活、玩弄感情的人,于是,徵信社應運而生。這不知道是人們的福 音還是不幸,希望天下的每一個人都歡樂著、幸福著。坐月子是女人一生的大事,女人可以为了襁褓中的婴儿放弃一直引用的红酒而吃月子餐,这时候的女人是幸福 而伟大的。有人歡喜有人優,有人狂笑有人大哭,我不想看到女人太多的眼淚,辭職后,我做了一位安靜、平和的室內設計師。虽然上下班没有了车接车送,但我租 车怡然自得。偶爾和Fake Rolex Watch, Breitling Replica Watch, Best replica watches, Omega Replica Watches ecosway的朋友小聚,很愜意

    July 24
    No namewrote:
    不動産投資 システム開発 札幌 不動産 仙台 不動産 大阪 不動産 横浜 不動産 名古屋 不動産 福岡 不動産 京都 不動産 埼玉 不動産 千葉 不動産 静岡 不動産 神戸 不動産 浜松 不動産 堺市 不動産 川崎市 不動産 相模原市 不動産 姫路 不動産 岡山 不動産 明石 不動産 鹿児島 不動産 北九州市 不動産 熊本 不動産 インテリアコーディネータ リフォーム 東京 リフォーム 大阪 不動産 査定 不動産 買取 不動産 売買 不動産 鑑定 不動産 売却 サイトを検索すると会社があったよくみると賃貸 住宅収益物件不動産 賃貸賃貸マンション新築マンションもしっかりカバーしてありすごく充実したさいとでもちろん投資を目的の方やリフォームをしたい人もすごく参考になるだう。ところで今、SEO対策などいまはやっているがホームページ制作会社にいらいしてもうまくはいかないようだ。最近私は、資産運用にこっていて税金対策にインテリアを集めている。もちろんファッションにこだわりブランド品や下着にはこだわりがある。 化粧品も高価なものがよく家具も最高級しか買わない、先日海外旅行にいってきてお土産に外車結婚指輪と高級時計をかったが、日本でしらべたら通販ですごく安く売っていた。
    今、会社の寮で賃貸を探してまして全部で12都市で社員が住みます場所は、福岡 賃貸,広島 賃貸,川崎 賃貸,神戸 賃貸,京都 賃貸,名古屋 賃貸,大阪 賃貸,埼玉 賃貸,札幌 賃貸,仙台 賃貸,千葉 賃貸,横浜 賃貸の政令指定都市が対象です不動産賃貸投資とは収益物件探し新築住宅アパートマンション土地から不動産投資
    July 19
    No namewrote:
    wow gold!All USwow gold Server 29.99$/1000G on sell! Cheap wow power leveling, Buy wow power leveling,Cheap wow power leveling,Buy Cheapest/Safe/Fast wow gold US EU wow power leveling Cheap lotro goldand Fast rolex watchInstant rolex Deliveryrolexchangyongkuivip
    Apr. 2
    shli wuwrote:
    可以用java语言开发一个基于 java的xpcom组件? 可以给个例子吗? 我知道java可以调用xpcom, 不知道还可以写呢?我在论坛里看到的信息是,不能用java开发xpcom组件的。
    Dec. 5

    Trackbacks

    The trackback URL for this entry is:
    http://liumspace.spaces.live.com/blog/cns!BC24129FC2E42AFD!122.trak
    Weblogs that reference this entry
    • None