Hessian 3.2.0的两个bug(转)

本文记录了将Hessian从3.0.13升级到3.2.0时遇到的两个bug及ClassLoader处理策略变化。Bug1涉及HessianInput的readObject方法失效问题;Bug2则是在特定条件下反序列化long[]数组时出现错误。此外,还介绍了3.2.0中ClassLoader获取策略的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hessian 3.2.0的两个bug

在将Hessian从3.0.13升级到3.2.0时碰到两个bug和一个ClassLoader处理策略的改变的问题,在此记录下,希望能为使用Hessian 3.2.0的同学们提供点帮助,避免再走同样的弯路。

Bug 1:HessianInput的readObject(Class)无效
对于使用Hessian 1的同学而言,有可能会使用到HessianInput的readObject(Class)这个方法,以实现将输入流反序列化为指定的类实例,这在有一个场景中是很需要的,例如序列化时序列化的是一个子类对象,但反序列化时需要反序列化为父类,这个时候就非常需要这方法了,在Hessian 3.2.0之前的版本中这个没有问题,但升级到3.2.0后就出现问题了,指定了Class会无效。
跟踪Hessian 3.2.0代码,发现它把之前版本的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信息,其他都会写,所以就导致了这个地方大多数情况下都会无视传入的指定的Class类型,更让人郁闷的是,去看Hessian2Input.readObject(Class)方法,它的处理方式就是正确的,在type不为""的情况下,它的处理方式为:
Deserializer reader;
    reader 
=  findSerializerFactory().getObjectDeserializer(type, cl);

    
return  reader.readMap( this );
而默认的SerializerFactory的getObjectDeserializer的实现如下:
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);
从上面这段代码的实现来看,是可以满足传入指定的Class类型的方式的需求的。

因此修正这个BUG的方法为,继承HessianInput,并覆盖它的readObject(Class)方法,将其中type不为""的处理方式改成和Hessian2Input一样,重新测试,OK。
这个Bug即使到最新的Hessian 3.2.1里也没有修复,因此暂时仍然需要自行处理。

Bug 2:当Map中或对象中有两个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[]数组是不会抛异常的,诡异呀,跟踪Hessian 3.2.0代码,发现有个很诡异的地方,在有两个数组后,Hessian会调用BasicDeserializer中的readLengthList方法,这个方法中竟然没有对long[]数组的处理,而只有对其他布尔型数组、短整型数组、整型数组等的处理,而当long[]数组的情况调用这个方法时,即抛出了UnsupportedOperationException异常,而更搞的是BasicDeserializer中的readList方法中是有对long[]数组的处理的,于是基本可以判断是Hessian的开发者漏写了对long[]的处理。
修正这个bug可以采用这两种方法:
1、修改BasicDeserializer,在readLengthList方法中加上对LONG_ARRAY的处理;
2、升级为Hessian 3.2.1,修复了这个bug,修复方法和1相同。

在升级到Hessian 3.2.0或3.2.1时还有个需要注意的问题,对于有些需要操作序列化时ClassLoader的同学有可能会碰到,Hessian 3.2.0以前的版本是在反序列化之前获取线程上下文ClassLoader来获取Class的,但在3.2.0+后,改变了这个策略,改为了在SerializerFactory实例化的时候就去获取线程上下文ClassLoader,以后在反序列化时就不再去获取了,这个方式对于需要控制ClassLoader的同学来说会有点麻烦,但还好Hessian还提供了一个方式,就是允许在创建SerializerFactory对象时传入ClassLoader,这就爽了,不用像以前一样需要通过控制线程上下文ClassLoader了,这种方式更为优雅,值得推荐。

转载于:https://www.cnblogs.com/echozhjun/archive/2011/01/02/1924082.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值