美文网首页
浅谈hession2序列化

浅谈hession2序列化

作者: 微博云玩家 | 来源:发表于2022-02-14 23:49 被阅读0次

        最近工作中遇到了个问题:在通过dubbo进行服务间通信时,暴露给调用方使用的返回值对象里面重载了带参数的构造函数,之后偷懒就没有另外声明无参的构造方法(这是个非常糟糕且低级的坏习惯,大家千万别模仿),导致在调用方,返回值进行反序列化时报错失败,随即马上补充无参的构造方法,优先保障系统正常迭代。服务间通信使用的dubbo,采用的序列化方式为hession2,后续对hession2的序列化进行了详细的了解,在此进行记录。 

        从示例代码出发进行分析。序列化就以Student对象为例进行,我一开始出现问题的代码没有无参的构造方法,其他都与示例代码基本等同。

    student对象

        序列化反序列化代码为

    序列化反序列化代码

        由于出问题的部分是反序列化阶段,那我们就先来看看反序列化里面都做了什么事情。如上图中序列化反序列化代码可见,反序列化执行的入口为input.readObject();通过打断点可以找到具体执行位置为

        ObjectDefinition中包含了序列化对象的全限定名,我们再接着往readObjectInstance里面看

            def.getType()就是获取序列化对象的全限定名,按照上一张图片中的调用方式,这里的cl应该为null,所以逻辑会走到else里面,我们先来看看findSerializerFactory做了什么

            如果_serializerFactory为空直接返回,否则返回一个新建的SerializerFactory,_serializerFactory默认情况下是为null的,所以这里返回一个新建的SerializerFactory,同时赋值给_serializerFactory。拿到factory后调用readObject方法。

            readObject方法里面先根据类的全限定名找到对应的反序列化器,获取反序列化器的过程比较复杂这里先跳过,最后拿到的反序列化器是JavaDeserializer。可以看到如果我们没找到合适的反序列化器,那么这里就会用MapDeserializer进行兜底反序列化。接下来我们再看看JavaDeserializer是如何执行的

            可以看到,在JavaDeserializer里面,先进行了反序列化对象的实例化,然后进行属性的填充,而我这次遇到的问题就发生在对象的实例化过程中,实例化过程即为instantiate方法实现。

        可以看到,实例化的方式是通过反射调用被反序列化类的构造方法,那么如果我有多个构造方法且构造方法需要参数时,是怎么确定用哪个构造方法以及如何获取参数的呢。答案就在序列化器的初始化中,代码长度问题,我们分两部分来看,第一部分是构造方法的选择

            从这部分可以看出来,通过反射获取到类的所有构造方法,然后选择成本最低的那个,成本如何计算?成本计算规则就是看构造方法参数的复杂程度。OK,接下来还有个问题,那就是调用构造方法时的构造参数如何获取

            通过构造方法拿到参数类型列表后,遍历并调用getParamArg方法获取入参,看来getParamArg就是关键所在了。

            可以看出在getParamArg方法中,对于非基本类型的一律返回null,对基本类型的返回对应类型的0值。这个时候回到我遇到的问题上,当Student类没有无参的构造方法时,只能选择有参的构造方法,这个时候有参的方法调用时会传入null作为参数,对null调用getXXX方法抛出NPE问题,导致反序列化失败。至此,反序列化链路也比较清晰了:获取对应的反序列化器->选择成本最小的构造方法用来实例化对象->如果有入参,选用对应类型的默认值->实例化对象->将字节码填充到刚刚实例化完成的对象中->反序列化完成。

            总的来说,还是要保持一个良好的开发习惯,在声明有参的构造方法时一定要加上无参的构造方法,不要偷懒。良好的开发习惯能避免很多不必要的麻烦。

            我们再对序列化进行一个拓展,序列化/反序列化机制大体分为两类:基于Bean属性访问机制、基于Field机制。基于Bean的是通过翻着调用getter/setter访问对象属性,基于Field的是通过反射或native方法直接对字段进行访问。

    相关文章

      网友评论

          本文标题:浅谈hession2序列化

          本文链接:https://www.haomeiwen.com/subject/sdcowltx.html