<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Equinox加載Bundle Class的實現

    對于想使用Equinox來構建OSGi應用的同學們而言,掌握Equinox是如何加載Bundle中的Class無疑是相當重要的,這樣在碰到各類ClassNotFoundException的時候也就有底了,否則可能出現的ClassNotFoundException會多的讓你非常的頭疼,本文提取自《OSGi原理與最佳實踐》,介紹下equinox是如何來加載Bundle中的class的。

    Equinox在創建BundleClassLoader時,首先獲取bundleclasspath,然后執行createBCLPrevileged方法,此方法最后轉交由BaseData來創建ClassLoader

    BaseDate創建ClassLoader的關鍵代碼片段為:

        ClassLoadingHook[] hooks = adaptor.getHookRegistry().getClassLoadingHooks();

        ClassLoader parent = adaptor.getBundleClassLoaderParent();

        BaseClassLoader cl = null;

        for (int i = 0; i < hooks.length && cl == null; i++)

           cl = hooks[i].createClassLoader(parent, delegate, domain, this, bundleclasspath);

        if (cl == null)

           cl = new DefaultClassLoader(parent, delegate, domain, this, bundleclasspath);

        return cl;

    Equinox中,默認的情況下adaptor.getBundleClassLoaderParent返回的為bootstrap  classloader,可通過修改啟動的osgi.parentClassLoader來改變這個parent classloader,默認值采用的boot,可選的其他值有:appextfwkapp對應的為SystemClassLoaderext對應的為SystemClassLoaderparentfwk對應的為啟動EquinoxClassLoaderClassLoadingHookcreateClassLoader的時候都沒有做動作,因此最后ClassLoader都是通過創建DefaultClassLoader對象來構建的,其中parent參數為nulldelegate參數為BundleLoader實例,bundleclasspath參數為bundleclasspath

    經過以上步驟后,完成了ClassLoader的創建,可以開始加載class了,根據上面上述,BundleClass就由DefaultClassLoader來完成了。

    查看DefaultClassLoaderloadClass代碼,發現真正的加載class的過程是轉為調用了delegatefindClass來完成的,delegate參數對應的為BundleLoader實例,轉為跟蹤BundleLoaderfindClass方法。

    BundleLoaderfindClass方法的代碼片段:

        if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE))

           return parentCL.loadClass(name);

    從以上這個代碼片段,可以看到,Equinoxjava.開頭的類轉交給了parent classloader去加載,這也意味著沒必要在系統中提供對外export java.開頭的package

    如果不是java.開頭的類,則交由findClassInternal方法來完成加載。

    findClassInternal方法遵循的為OSGi規范中定義的Class的加載順序,不過仍然稍有改動:

    1)         判斷是否交由parent classloader去完成加載

    在啟動Equinox時,Equinox會讀取org.osgi.framework.bootdelegation屬性,該屬性對應配置的為需要從parent classloader中加載的package,如值配置的為*,說明所有的都從parent classloader中加載,如值配置的為具體的package,那么則放入bootDelegation集合;如配置的為帶通配符的package,那么則放入bootDelegationStems集合。

    判斷時Equinox首先判斷是否所有的都從parent classloader中加載,如是則從parent classloader中加載;

    如需要加載的類的package位于bootDelegationbootDelegationStems集合中,那么同樣從parent classloader中加載。

    如不從parent classloader中加載,則進入下面的步驟。

    2)         嘗試調用Equinox提供的ClassLoaderDelegateHook的擴展來加載

    Equinox對外提供了ClassLoaderDelegateHook的接口擴展,可編寫ClassLoaderDelegateHook的實現,注冊到Framework中,那么當有Class需要加載等動作時都會得到通知。

    在默認情況下,Equinox中沒有ClassLoaderDelegateHook的實現,因此繼續下面的步驟。

    3)         判斷是否在import-package中,如在則交由相應的PackageSource去加載

    根據Bundle配置的import-package,判斷目前需要加載的類是否在import-package中,如在則交由對應的PackageSource進行加載,PackageSource在加載時即直接交由對應的Bundleclassloader去加載,如加載的類的packageimport-package中,但加載后仍然沒有找到Class,則直接拋出ClassNotFoundException,如加載到,則直接返回。

    如所需要加載的類不的package不在import-package中,則繼續下面的步驟。

    4)         嘗試從require-bundle中加載

    嘗試使用require-bundle來加載,如加載到,則直接返回,如加載不到,則繼續下面的步驟。

    5)         嘗試從當前Bundle中加載

    直到經過以上步驟的嘗試,才嘗試由當前Bundle中加載,當前Bundle加載的方法即從Bundle-Classpath或當前BundleFragment中查找相應名稱的class文件,并讀取該文件進行加載,如class文件已加載,則進行緩存,再次加載時則不需要查找和解析class文件。

    如從當前Bundle中仍然未找到所需的類,則繼續下面的步驟。

    6)         嘗試從DynamicImport-Package中加載

    判斷需要找的類的package是否在DynamicImport-Package中,如果在,則交由相應的PackageSource進行加載,如PackageSource中加載不到,則拋出ClassNotFoundException;如不在DynamicImport-Package中,則繼續下面的步驟。

    7)         再次嘗試調用Equinox提供的ClassLoaderDelegateHook的擴展來加載

    這步和第2)步相同,因此在默認情況下繼續下面的步驟。

    8)         嘗試使用eclipsebuddy機制來加載

    Buddy機制是Eclipse的擴展,并不符合OSGi規范,因此在此不做深入分析。

    9)         判斷一定的條件,如符合則從parent classloader中加載

    判斷的條件為:parent classloader不為null、不從parent classloader中加載、Equinox的向后兼容屬性(osgi.compatibility.bootdelegation)為true以及jvmbug class,如滿足以上條件,則嘗試從parent classloader中加載。

    如經過以上所有步驟后,仍然未找到需要加載的class,則拋出ClassNotFoundException

    從上面的代碼分析中,在Equinox中可以通過osgi.parentClassLoaderorg.osgi.framework.bootdelegation來控制從Bundle ClassLoader外來加載Class,這對于集成Equinox其他容器而言,非常有用,另外,還可以通過實現ClassLoaderDelegateHook來改變Class的加載。

    posted on 2009-05-10 17:25 BlueDavy 閱讀(6683) 評論(12)  編輯  收藏 所屬分類: OSGi、SOA、SCA

    評論

    # re: Equinox加載Bundle Class的實現 2009-05-10 20:15 galaxystar

    頂一下畢老大  回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-16 22:31 Kane

    應該附帶把Equniox的findLibrary一起講了
    :)  回復  更多評論   

    # re: Equinox加載Bundle Class的實現[未登錄] 2009-05-20 16:57 jame

    今天剛好遇到一個Bundle中調用javax.xml的問題,一至報ClassNotFoundException:javax.xml.parsers.SAXParserFactory錯誤.

    http://docs.codehaus.org/display/JETTY/OSGi+Tips
    中是這么說的:
    All of these, except for javax.mail, org.apache.tools.ant. and org.eclipse.jdt. can all be found in the jvm's rt.jar. In Equinox, by default, these system packages from the system classloader are not exposed inside the OSGi framework. So, we need to expose them by using this setup in the config.ini:

    org.osgi.framework.system.packages=javax.naming, javax.naming.directory, javax.naming.spi, javax.management, javax.management.loading, javax.management.modelmbean, javax.net, javax.net.ssl, javax.crypto, javax.crypto.interfaces, javax.crypto.spec, javax.security.auth, javax.security.auth.spi, javax.security.auth.callback, javax.security.auth.login, javax.security.cert, javax.xml.parsers, javax.xml.xpath, javax.xml.transform.sax, javax.xml.transform.dom, javax.xml.namespace, javax.xml.transform, javax.xml.transform.stream, javax.xml.validation, org.xml.sax, org.xml.sax.helpers, org.xml.sax.ext, com.sun.org.apache.xalan.internal, com.sun.org.apache.xalan.internal.res, com.sun.org.apache.xml.internal.utils, com.sun.org.apache.xpath.internal, com.sun.org.apache.xpath.internal.jaxp, com.sun.org.apache.xpath.internal.objects, com.sun.org.apache.xml.internal, org.w3c.dom, org.w3c.dom.traversal, org.w3c.dom.ls, javax.sql, javax.transaction, sun.misc

    但加上這些package后還是沒有解決....最后發現要加
    org.osgi.framework.bootdelegation=*這句.

    找了一個下午,汗.......

    BlueDavy什么時候能詳細說一下config.ini中主要配置的作用嗎?
    如:http://tieba.baidu.com/f?kz=76392347這里列出來的這些...
    期待....
      回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-20 17:52 Kane

    import javax.* in Import-package header  回復  更多評論   

    # re: Equinox加載Bundle Class的實現[未登錄] 2009-05-21 09:42 jame

    @Kane
    Import-Package: javax.xml;version="1.3.0",
    javax.xml.datatype;version="1.3.0",
    javax.xml.namespace;version="1.3.0",
    javax.xml.parsers;version="1.3.0",
    org.osgi.framework

    啟動時報:
    org.osgi.framework.BundleException: The bundle could not be resolved. Reason: Missing Constraint: Import-Package: javax.xml; version="1.3.0"

    正常的java文件中是能import javax.xml.parsers.*;
    應該是OSGI ClassLoader的特殊性.

    之前在Eclipse3.4中測試是會沒這個問題的,當通過命令行方式來啟動equinox時才遇到這個問題.
    按此BLOG中講的在configuration\config.ini中添加org.osgi.framework.bootdelegation=*解決問題  回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-21 10:49 BlueDavy

    @jame
    ...配置成*的話,所有類都會從bootstrap classloader里裝載的,應該只配javax.*
      回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-21 11:00 Kane

    @jame
    org.osgi.framework.bootdelegation=*并不是好的解決辦法,它讓OSGi的classloader的模塊化特性丟失了。
    我覺得通過指定org.osgi.framework.system.packages是更好的辦法,比如
    -Dorg.osgi.framework.system.packages=javax.accessibility,javax.activation,javax.activity,javax.annotation, javax.annotation.processing,javax.crypto,javax.crypto.interfaces,javax.crypto.spec,javax.imageio,javax.i mageio.event,javax.imageio.metadata...
      回復  更多評論   

    # re: Equinox加載Bundle Class的實現[未登錄] 2009-05-21 13:19 jame

    @Kane
    這種方式與在config.ini配置有區別嗎?
    我配置在config.ini中的時候好象不想作用?

    @BlueDavy
    如果一個正在運行OSGI的項目中新增一個Bundle,但這個新增的Bundle需要用到java以外package中的類,有沒有其他更好的方法?如果改配置那得重啟整個項目了....(就如修改Eclipse中某些配置后需要重啟才能生效?)
      回復  更多評論   

    # re: Equinox加載Bundle Class的實現[未登錄] 2009-05-21 13:28 jame

    @Kane
    這是我run.bat中的內容,剛才測試這種方法好象不能解決這個問題.是不是還是設置其他項?(config.ini org.osgi.framework.bootdelegation=javax.*,org.*除外)

    @echo off
    java -Xms128m -Xmx512m -Dorg.osgi.service.http.port=8111 -Dorg.osgi.framework.system.packages=javax.naming,javax.naming.directory,javax.naming.spi... -jar org.eclipse.osgi_3.4.3.R34x_v20081215-1030.jar -configuration ../configuration -console  回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-21 15:15 BlueDavy

    @jame
    如果新增的bundle需要用到java以外package的類,通常做法是把依賴的類也打到一個bundle,然后對外export..
      回復  更多評論   

    # re: Equinox加載Bundle Class的實現 2009-05-21 15:16 BlueDavy

    @jame
    在Equinox中,另外一種方法就是自己實現ClassLoadingHook,就可以自己控制了。  回復  更多評論   

    # re: Equinox加載Bundle Class的實現[未登錄] 2009-05-21 16:55 jame

    @BlueDavy
    謝謝指點...

    新書什么時候出版,期待....  回復  更多評論   

    公告

     









    feedsky
    抓蝦
    google reader
    鮮果

    導航

    <2009年5月>
    262728293012
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    統計

    隨筆分類

    隨筆檔案

    文章檔案

    Blogger's

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲国产成人精品无码区在线网站| 亚洲成av人片一区二区三区| 国产精品免费观看久久| 最新69国产成人精品免费视频动漫| 永久免费观看的毛片的网站| 亚洲国产日韩成人综合天堂 | 少妇太爽了在线观看免费视频| 曰批全过程免费视频播放网站| 美女裸身网站免费看免费网站| 免费理论片51人人看电影| 亚洲男人第一无码aⅴ网站| 亚洲AV无码成人网站久久精品大| 亚洲福利一区二区精品秒拍| 亚洲成熟丰满熟妇高潮XXXXX| 一级做a爰片性色毛片免费网站| 久久黄色免费网站| 大陆一级毛片免费视频观看| 最新精品亚洲成a人在线观看| 亚洲黄网站wwwwww| 另类专区另类专区亚洲| 日韩免费在线观看视频| 我要看WWW免费看插插视频| 亚洲男女内射在线播放| 亚洲国产综合在线| 人妻无码中文字幕免费视频蜜桃 | 全部免费毛片在线播放| 白白国产永久免费视频| 亚洲乱码无码永久不卡在线| 亚洲国产av高清无码| 春意影院午夜爽爽爽免费| 99久9在线|免费| 免费又黄又爽的视频| 亚洲视频在线观看网站| 国产亚洲福利一区二区免费看| 久久精品免费观看国产| 在线观看免费亚洲| 亚洲黄色免费观看| 一级毛片免费播放试看60分钟 | 免费人成毛片动漫在线播放| 看全色黄大色大片免费久久| 亚洲韩国—中文字幕|