新聞中心
Equinox在創(chuàng)建Bundle的ClassLoader時(shí),首先獲取bundle的classpath,然后執(zhí)行createBCLPrevileged方法,此方法***轉(zhuǎn)交由BaseData來創(chuàng)建ClassLoader。

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出定南免費(fèi)做網(wǎng)站回饋大家。
BaseDate創(chuàng)建ClassLoader的關(guān)鍵代碼片段為:
- 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中,默認(rèn)的情況下adaptor.getBundleClassLoaderParent返回的為bootstrap classloader,可通過修改啟動(dòng)的osgi.parentClassLoader 來改變這個(gè)parent classloader,
osgi.parentClassLoader 的可選值有四個(gè),分別是:
l boot : 默認(rèn)
l app : SystemClassLoader
l ext : SystemClassLoader的parent
l fwk : 啟動(dòng)Equinox的ClassLoader
ClassLoadingHook在createClassLoader的時(shí)候都沒有做動(dòng)作,因此***ClassLoader都是通過創(chuàng)建DefaultClassLoader對(duì)象來構(gòu)建的,其中parent參數(shù)為null,delegate參數(shù)為BundleLoader實(shí)例,bundleclasspath參數(shù)為bundle的classpath。
經(jīng)過以上步驟后,完成了ClassLoader的創(chuàng)建,可以開始加載class了,根據(jù)上面上述,Bundle的Class就由DefaultClassLoader來完成了。
查看DefaultClassLoader的loadClass代碼,發(fā)現(xiàn)真正的加載class的過程是轉(zhuǎn)為調(diào)用了delegate 的findClass來完成的,delegate參數(shù)對(duì)應(yīng)的為BundleLoader實(shí)例,轉(zhuǎn)為跟蹤BundleLoader的findClass方法。
BundleLoader的findClass方法的代碼片段:
- if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE))
- return parentCL.loadClass(name);
從以上這個(gè)代碼片段,可以看到,Equinox將java.開頭的類轉(zhuǎn)交給了parent classloader去加載,這也意味著沒必要在系統(tǒng)中提供對(duì)外export java.開頭的package。
如果不是java.開頭的類,則交由findClassInternal方法來完成加載。
findClassInternal方法遵循的為OSGi規(guī)范中定義的Class的加載順序,不過仍然稍有改動(dòng):
1) 判斷是否交由parent classloader去完成加載
在啟動(dòng)Equinox時(shí),Equinox會(huì)讀取org.osgi.framework.bootdelegation屬性,該屬性對(duì)應(yīng)配置的為需要從parent classloader中加載的package,如值配置的為*,說明所有的都從parent classloader中加載 ,如值配置的為具體的package,那么則放入bootDelegation集合;如配置的為帶通配符的package,那么則放入bootDelegationStems集合。
判斷時(shí)Equinox首先判斷是否所有的都從parent classloader中加載,如是則從parent classloader中加載;
如需要加載的類的package位于bootDelegation或bootDelegationStems集合中,那么同樣從parent classloader中加載。
如不從parent classloader中加載,則進(jìn)入下面的步驟。
2) 嘗試調(diào)用Equinox提供的ClassLoaderDelegateHook的擴(kuò)展來加載
Equinox對(duì)外提供了ClassLoaderDelegateHook的接口擴(kuò)展,可編寫ClassLoaderDelegateHook的實(shí)現(xiàn),注冊(cè)到Framework中,那么當(dāng)有Class需要加載等動(dòng)作時(shí)都會(huì)得到通知。
在默認(rèn)情況下,Equinox中沒有ClassLoaderDelegateHook的實(shí)現(xiàn),因此繼續(xù)下面的步驟。
3) 判斷是否在import-package中,如在則交由相應(yīng)的PackageSource去加載
根據(jù)Bundle配置的import-package,判斷目前需要加載的類是否在import-package中,如在則交由對(duì)應(yīng)的PackageSource進(jìn)行加載,PackageSource在加載時(shí)即直接交由對(duì)應(yīng)的Bundle的classloader去加載,如加載的類的package在import-package中,但加載后仍然沒有找到Class,則直接拋出ClassNotFoundException,如加載到,則直接返回。
如所需要加載的類的package不在import-package中,則繼續(xù)下面的步驟。
4) 嘗試從require-bundle中加載
嘗試使用require-bundle來加載,如加載到,則直接返回,如加載不到,則繼續(xù)下面的步驟。
5) 嘗試從當(dāng)前Bundle中加載
直到經(jīng)過以上步驟的嘗試,才嘗試由當(dāng)前Bundle中加載,當(dāng)前Bundle加載的方法即從Bundle-Classpath或當(dāng)前Bundle的Fragment中查找相應(yīng)名稱的class文件,并讀取該文件進(jìn)行加載,如class文件已加載,則進(jìn)行緩存,再次加載時(shí)則不需要查找和解析class文件。
如從當(dāng)前Bundle中仍然未找到所需的類,則繼續(xù)下面的步驟。
6) 嘗試從DynamicImport-Package中加載
判斷需要找的類的package是否在DynamicImport-Package中,如果在,則交由相應(yīng)的PackageSource進(jìn)行加載,如PackageSource中加載不到,則拋出ClassNotFoundException;如不在DynamicImport-Package中,則繼續(xù)下面的步驟。
7) 再次嘗試調(diào)用Equinox提供的ClassLoaderDelegateHook的擴(kuò)展來加載
這步和第2)步相同,因此在默認(rèn)情況下繼續(xù)下面的步驟。
8) 嘗試使用eclipse的buddy機(jī)制來加載
Buddy機(jī)制是Eclipse的擴(kuò)展,并不符合OSGi規(guī)范,因此在此不做深入分析。
9) 判斷一定的條件,如符合則從parent classloader中加載
判斷的條件為:parent classloader不為null、不從parent classloader中加載、Equinox的向后兼容屬性(osgi.compatibility.bootdelegation)為true以及jvm的bug class,如滿足以上條件,則嘗試從parent classloader中加載。
如經(jīng)過以上所有步驟后,仍然未找到需要加載的class,則拋出ClassNotFoundException。
從上面的代碼分析中,在Equinox中可以通過osgi.parentClassLoader、org.osgi.framework.bootdelegation來控制從Bundle ClassLoader外來加載Class,這對(duì)于集成Equinox其他容器而言,非常有用,另外,還可以通過實(shí)現(xiàn)ClassLoaderDelegateHook來改變Class的加載。
名稱欄目:Equinox加載BundleClass的實(shí)現(xiàn)
新聞來源:http://m.5511xx.com/article/dpphcjd.html


咨詢
建站咨詢
