Hessian 3.2.0的兩個bug

          在將Hessian從3.0.13升級到3.2.0時碰到兩個bug和一個ClassLoader處理策略的改變的問題,在此記錄下,希望能為使用Hessian 3.2.0的同學(xué)們提供點幫助,避免再走同樣的彎路。

          Bug 1:HessianInput的readObject(Class)無效
          對于使用Hessian 1的同學(xué)而言,有可能會使用到HessianInput的readObject(Class)這個方法,以實現(xiàn)將輸入流反序列化為指定的類實例,這在有一個場景中是很需要的,例如序列化時序列化的是一個子類對象,但反序列化時需要反序列化為父類,這個時候就非常需要這方法了,在Hessian 3.2.0之前的版本中這個沒有問題,但升級到3.2.0后就出現(xiàn)問題了,指定了Class會無效。
          跟蹤Hessian 3.2.0代碼,發(fā)現(xiàn)它把之前版本的HessianInput的readObject(Class)方法做了改動,改為了:
              String type = readType();

                
          // hessian/3386
                if ("".equals(type)) {
              Deserializer reader;
              reader 
          = _serializerFactory.getDeserializer(cl);

              
          return reader.readMap(this);
                }
                
          else {
              Deserializer reader;
              reader 
          = _serializerFactory.getObjectDeserializer(type);

                  
          return reader.readMap(this);
                }
          從上面代碼可以看出,只要序列化流中有類型信息,那么就完全忽視傳入的指定的Class類型,而在hessian中貌似只有Map類型的才不會寫type信息,其他都會寫,所以就導(dǎo)致了這個地方大多數(shù)情況下都會無視傳入的指定的Class類型,更讓人郁悶的是,去看Hessian2Input.readObject(Class)方法,它的處理方式就是正確的,在type不為""的情況下,它的處理方式為:
          Deserializer reader;
              reader 
          = findSerializerFactory().getObjectDeserializer(type, cl);

              
          return reader.readMap(this);
          而默認(rèn)的SerializerFactory的getObjectDeserializer的實現(xiàn)如下:
          Deserializer reader = getObjectDeserializer(type);
              
              
          if (cl == null
              
          || cl.equals(reader.getType())
              
          || cl.isAssignableFrom(reader.getType())
              
          || HessianHandle.class.isAssignableFrom(reader.getType())) {
                
          return reader;
              }

              
          if (log.isLoggable(Level.FINE)) {
                log.fine(
          "hessian: expected '" + cl.getName() + "' at '" + type + "' ("
                     
          + reader.getType().getName() + ")");
              }
              
              
          return getDeserializer(cl);
          從上面這段代碼的實現(xiàn)來看,是可以滿足傳入指定的Class類型的方式的需求的。

          因此修正這個BUG的方法為,繼承HessianInput,并覆蓋它的readObject(Class)方法,將其中type不為""的處理方式改成和Hessian2Input一樣,重新測試,OK。
          這個Bug即使到最新的Hessian 3.2.1里也沒有修復(fù),因此暫時仍然需要自行處理。

          Bug 2:當(dāng)Map中或?qū)ο笾杏袃蓚€long[]時反序列化出錯
          這個問題還真要湊巧才能碰上,大家可以自己寫段簡單的程序測試一下,用Hessian2Input和Hessian2Output去完成下面datas對象的序列化和反序列化:
          Map<String,Object> datas=new HashMap<String,Object>();
          datas.put(
          "1",new long[]{1L,-1L});
          datas.put(
          "2",new long[]{2L,-2L});
          反序列化的時候會拋出UnsupportedOperationException或java.util.Map cannot assigned from null這樣的異常信息,而且如果Map中只有一個long[]數(shù)組是不會拋異常的,詭異呀,跟蹤Hessian 3.2.0代碼,發(fā)現(xiàn)有個很詭異的地方,在有兩個數(shù)組后,Hessian會調(diào)用BasicDeserializer中的readLengthList方法,這個方法中竟然沒有對long[]數(shù)組的處理,而只有對其他布爾型數(shù)組、短整型數(shù)組、整型數(shù)組等的處理,而當(dāng)long[]數(shù)組的情況調(diào)用這個方法時,即拋出了UnsupportedOperationException異常,而更搞的是BasicDeserializer中的readList方法中是有對long[]數(shù)組的處理的,于是基本可以判斷是Hessian的開發(fā)者漏寫了對long[]的處理。
          修正這個bug可以采用這兩種方法:
          1、修改BasicDeserializer,在readLengthList方法中加上對LONG_ARRAY的處理;
          2、升級為Hessian 3.2.1,修復(fù)了這個bug,修復(fù)方法和1相同。

          在升級到Hessian 3.2.0或3.2.1時還有個需要注意的問題,對于有些需要操作序列化時ClassLoader的同學(xué)有可能會碰到,Hessian 3.2.0以前的版本是在反序列化之前獲取線程上下文ClassLoader來獲取Class的,但在3.2.0+后,改變了這個策略,改為了在SerializerFactory實例化的時候就去獲取線程上下文ClassLoader,以后在反序列化時就不再去獲取了,這個方式對于需要控制ClassLoader的同學(xué)來說會有點麻煩,但還好Hessian還提供了一個方式,就是允許在創(chuàng)建SerializerFactory對象時傳入ClassLoader,這就爽了,不用像以前一樣需要通過控制線程上下文ClassLoader了,這種方式更為優(yōu)雅,值得推薦。

          posted on 2009-08-06 11:19 BlueDavy 閱讀(9136) 評論(0)  編輯  收藏 所屬分類: Java

          公告

           









          feedsky
          抓蝦
          google reader
          鮮果

          導(dǎo)航

          <2009年8月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統(tǒng)計

          隨筆分類

          隨筆檔案

          文章檔案

          Blogger's

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 长葛市| 江山市| 西平县| 津南区| 疏勒县| 临武县| 泉州市| 称多县| 东兴市| 汉中市| 长武县| 商洛市| 乐亭县| 扎兰屯市| 明光市| 六盘水市| 嘉义市| 额尔古纳市| 瓮安县| 娄底市| 青海省| 旬阳县| 龙山县| 五寨县| 贺兰县| 永德县| 锡林郭勒盟| 高清| 南充市| 齐齐哈尔市| 三明市| 富源县| 乌兰浩特市| 江口县| 巩留县| 富宁县| 元江| 九江市| 花垣县| 叙永县| 邻水|