gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          equinox環境下開發bundle不需要引入java.*包而需要引入javax.*包的的原因

          ClassLoader(類加載器)是Java提供的抽象類,它是負責加載類的對象。ClassLoader 做的工作就是在JVM 中將類裝入內存。 當 JVM 需要使用類時,它根據名稱向 ClassLoader 請求這個類,然后 ClassLoader 返回一個表示這個類的 Class 對象。

          一、前提知識 ClassLoader


          ClassLoader(類 加載器)是Java提供的抽象類,它是負責加載類的對象。ClassLoader 做的工作就是在JVM 中將類裝入內存。 當 JVM 需要使用類時,它根據名稱向 ClassLoader 請求這個類,然后 ClassLoader 返回一個表示這個類的 Class 對象。


          所有java.*包內的類都是由ClassLoader完成加載的,而且在執行java命令的時候ClassLoaer就已經被裝入內存中。通常在開發過程中使用java.*包內的類的時候,不再需要import 這些類了。


          二、Bundle中的ClassLoader


          在equinox環境下,每一個bundle都有獨立的classLoader,對應的類名為BundleLoader。

          每個bundle的classLoader都有parent,這個parent(父classLoader)就是類的委派模型中的上一層的classLoader。對應的類名為ParentClassLoader,它是這樣定義的



          private static class ParentClassLoader extends ClassLoader {

           
          protected ParentClassLoader() {

            
          super(null);

           }

          }


          這是一個空的classloader,它直接繼承了java.lang.ClassLoader 。java包中的所有類都是由java.lang.ClassLoader載入的,根據類的委派模型可以知道,繼承了ClassLoader就可以直接獲得需要的java類。



                      if (name.startsWith(JAVA_PACKAGE))

                        
          // 1) if startsWith "java." delegate to parent and terminate search

                        
          // we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.

                          return parent.loadClass(name);


          上面代碼是bundle加載class的流程圖中的第一步,通過parentClassLoader獲得所需java.*包中的類,如下圖所示。



           這就是bundle中不需要引入java.*包的原因。


          三、如何知道java.*這些類已經被裝載了呢?


          1、寫一個類如下:



          public class  A

          {

              
          public static void main(String[] args) 

              {

                  System.out.println(
          "Hello World!");

              }

          }



          2、編譯



          javac A.java


          3、運行



          java -verbose A


          顯示的部分內容如下:



          [Loaded java.lang.Object from shared objects file]

          [Loaded java.io.Serializable from shared objects file]

          [Loaded java.lang.Comparable from shared objects file]

          [Loaded java.lang.CharSequence from shared objects file]

          [Loaded java.lang.String from shared objects file]

          [Loaded java.lang.reflect.GenericDeclaration from shared objects file]

          [Loaded java.lang.reflect.Type from shared objects file]

          [Loaded java.lang.reflect.AnnotatedElement from shared objects file]

          [Loaded java.lang.Class from shared objects file]

          [Loaded java.lang.Cloneable from shared objects file]

          [Loaded java.lang.ClassLoader from shared objects file]

          ... (后面還有很多,不一一列舉)


           


          四、為什么需要引入javax.*包


          下面的代碼是另一篇文章 equinox實現Class Loader機制的代碼解讀  提過的,bundle類載入的流程圖片段代碼。



            ...

            String pkgName 
          = getPackageName(name);

                  
          // follow the OSGi delegation model

                  if (checkParent && parent != null) ...{

                      
          if (name.startsWith(JAVA_PACKAGE))

                        
          // 1) if startsWith "java." delegate to parent and terminate search

                        
          // we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.

                          return parent.loadClass(name);

                      
          else if (isBootDelegationPackage(pkgName))

                          
          // 2) if part of the bootdelegation list then delegate to parent and continue of failure

                          try ...{

                              
          return parent.loadClass(name);

                          } 
          catch (ClassNotFoundException cnfe) ...{

                              
          // we want to continue

                          }

                  }

           ...


          從上面的代碼可以看出,如果不是第一種情況(包名不是以java.開始的)就使用第二個判斷條件。


          isBootDelegationPackage(pkgName)返回的是true(這個配置在以后再說),所以執行的是


          parent.loadClass(name);


          這 行代碼和第一個條件的代碼是一樣的,即還是使用parentClassLoader去加載javax.*的包。由于ClassLoader只加載了 java.*的包,所以這里是不能得到javax.*包中的類的,會導致 ClassNotFoundException 的錯誤。從上面的代碼可以知道,代碼中對ClassNotFoundException 沒有處理,而是 繼續執行了。分別從import package、required bundles、bundle內部classpath和dynamic import 獲取javax.*的包。


          通常情況下,這些javax.*的包作為required bundle提供,而且只需要提供一次,并避免在其他的bundle中再次/重復提供(export)。



                  PackageSource source = findImportedSource(pkgName);

                  if (source != null) {

                      
          // 3) found import source terminate search at the source

                      result = source.loadClass(name);

                      
          if (result != null)

                          
          return result;

                      
          throw new ClassNotFoundException(name);

                  }

                  
          // 4) search the required bundles

                  source = findRequiredSource(pkgName);

                  
          if (source != null)

                      
          // 4) attempt to load from source but continue on failure

                      result = source.loadClass(name);

                  
          // 5) search the local bundle

                  if (result == null)

                      result 
          = findLocalClass(name);

                  
          if (result != null)

                      
          return result;

                  
          // 6) attempt to find a dynamic import source; only do this if a required source was not found

                  if (source == null) {

                      source 
          = findDynamicSource(pkgName);


          這就是需要引入javax.*包的原因。

          posted on 2008-05-05 10:26 gembin 閱讀(973) 評論(0)  編輯  收藏 所屬分類: OSGi

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          free counters
          主站蜘蛛池模板: 拉萨市| 宜春市| 奇台县| 田阳县| 志丹县| 石狮市| 治多县| 奉化市| 陕西省| 东兰县| 施秉县| 三河市| 灌南县| 诸暨市| 乌拉特中旗| 宣化县| 石景山区| 光泽县| 广丰县| 武隆县| 汝州市| 滨州市| 临安市| 盖州市| 麻栗坡县| 江津市| 沁水县| 都江堰市| 钟祥市| 介休市| 延长县| 拜泉县| 定日县| 信丰县| 阿荣旗| 当阳市| 贞丰县| 廊坊市| 庄河市| 辽阳县| 汪清县|