Hessian/Java反序列化采用自定義的Classloader

          對于采用OSGi來做系統的人而言,ClassLoader的問題必然是頭號需要解決的問題,如果又是個需要遠程通訊的OSGi應用的話,那么反序列化的classloader問題幾乎可以肯定是會碰到的,來看看在如今流行的兩種序列化、反序列化協議:java/hessian中如何使用自定義的classloader。
          java/hessian并不提供直接的傳入ClassLoader類來改變反序列化時采用的ClassLoader,hessian采用的為使用當前線程的上下文ClassLoader來加載反序列化的類,java則采用堆棧上最近的一個ClassLoader類來加載,可以認為就是調用類所在的ClassLoader來加載,但在OSGi應用中,通常采用以上默認的行為來反序列化加載類是會出問題的,因此需要采用自定義的。
          先來看看java的,Java在ObjectInputStream.readObject時最后采用的是resolveClass方法來加載類:
          protected Class<?> resolveClass(ObjectStreamClass desc)
              
          throws IOException, ClassNotFoundException
              {
              String name 
          = desc.getName();
              
          try {
                  
          return Class.forName(name, false, latestUserDefinedLoader());
              } 
          catch (ClassNotFoundException ex) {
                  Class cl 
          = (Class) primClasses.get(name);
                  
          if (cl != null) {
                  
          return cl;
                  } 
          else {
                  
          throw ex;
                  }
              }
              }
          驚喜的是,resolveClass是protected的,:),還好,還留下了這一手,于是毫不客氣,寫一個繼承ObjectInputStream的子類,然后覆蓋resolveClass方法即可,到這步了就可以隨意用自己的ClassLoader來實現加載了。
          OK,java的解決了,來看Hessian的,Hessian在加載類的時候采用了下面的代碼:
          if (type.startsWith("[")) {
                Deserializer subDeserializer 
          = getDeserializer(type.substring(1));
                deserializer 
          = new ArrayDeserializer(subDeserializer);
              }
              
          else {
                
          try {
              ClassLoader loader 
          = Thread.currentThread().getContextClassLoader();
                
              Class cl 
          = Class.forName(type, false, loader);

              deserializer 
          = getDeserializer(cl);
                } 
          catch (Exception e) {
                }
              }
          看過這段代碼后,就明白,要替換,最明顯的一種做法是替換當前線程的上下文classloader,而這通常有一定的風險,因為可能會有很多代碼使用到線程的上下文classloader,另外一種可選的做法就是繼承SerializerFactory,覆蓋其中的getDeserializer方法,從而實現對加載類的ClassLoader的控制,這種方式風險就比較小了。
          為了能實現使用自定義的classloader后可以加載到所有bundle export package中的類,在自定義classloader所在的Bundle中需要加上DynamicImport-Package,這樣可以比較簡單的實現。
          在Equinox中,則還可以選擇實現ClassLoadingHook,這樣可以比較簡單的實現和其他外部容器的集成以及更加自如的控制classloader,:)
          在解決了classloader的問題后,通常來講,使用OSGi帶給你的更多的就是享受,而非痛苦了。

          posted on 2009-05-21 13:42 BlueDavy 閱讀(5958) 評論(0)  編輯  收藏 所屬分類: OSGi、SOA、SCA

          公告

           









          feedsky
          抓蝦
          google reader
          鮮果

          導航

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

          統計

          隨筆分類

          隨筆檔案

          文章檔案

          Blogger's

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 睢宁县| 台江县| 东港市| 盐池县| 辽宁省| 运城市| 会泽县| 金山区| 光山县| 仁布县| 芷江| 福建省| 阿城市| 丹阳市| 宁波市| 镶黄旗| 尚义县| 营口市| 浙江省| 高阳县| 堆龙德庆县| 本溪市| 介休市| 鸡泽县| 忻城县| 海口市| 遂昌县| 黔西| 叶城县| 西华县| 杭锦后旗| 广西| 辽阳县| 弋阳县| 施秉县| 商洛市| 安新县| 页游| 丹江口市| 耒阳市| 湘潭县|