美文网首页
浅谈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序列化

    最近工作中遇到了个问题:在通过dubbo进行服务间通信时,暴露给调用方使用的返回值对象里面重载了带参数的构造函...

  • Dubbo序列化之hessian2

    根据前面的说明可以知道序列化功能依然使用spi,我们来查看一下 很明显 默认情况我们使用hession2来作为序列...

  • 浅谈序列化(Serializable)

    在写这篇文章之前,当时正在看 Java 数据结构和集合框架的源码实现,正巧碰到了 ArrayList 源码中的两个...

  • IPC机制浅谈(序列化)

    简介 通信方式 使用场景 开启多进程模式 开启多进程的只有一种方法,那就是给四大组件在AndroidMenifes...

  • 浅谈jQuey表单序列化

    原创博客,转载请联系作者 使用表单序列化的好处是可以帮我们精简代码,减少不必要的ID的使用。 jQuery表格中提...

  • 浅谈JAVA的序列化与反序列化

    问题1:什么是序列化与反序列化?简单来说,序列化就是将JAVA对象转换成为二进制表示的字节数组,反序列化则是将字节...

  • 2020-07-02

    浅谈 浅谈模块设计宏内核 浅谈接口设计Flags 浅谈稳定性设计重试 浅谈人员业务结构设计矩阵式 浅谈接口设计 |...

  • 序列化和反序列细节处理

    python 中pickle 和 json 都是序列化和反序列化的模块。 关于序列化和反序列化 序列化和反序列化[...

  • 23_序列化和反序列化

    =======序列化 ========反序列化 不被序列化

  • Java中对象或者对象数组的序列化和反序列化

    1、序列化(反序列化)对象: 2、序列化(反序列化)对象数组:

网友评论

      本文标题:浅谈hession2序列化

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