Dubbo序列化-结合源码找问题

Posted DUBBO之家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo序列化-结合源码找问题相关的知识,希望对你有一定的参考价值。

点击上方“公众号”可以订阅哦


Dubbo之家

和你一起终身学习


#DH终身学习#  


首先交代背景,前几天遇到一个小bug,由于其他系统的一个DTO子类和父类有一个字段名重复了,所以导致我set的子类字段那边拿不到值。改起来很简单嘛,让对面把子类的字段删掉就好,但是拿不到值的原因让我想了很久,很明显是序列化和反序列化的过程中这个字段的值丢失了,但是到底是在哪一步呢?还是决定看看源码给自己一个答案。

dubbo 版本:2.6.7。

首先先确定协议和序列化的方式:

 
   
   
 
  1. <dubbo:protocol name="dubbo" port="${dubbo.port}" host="${dubbo.host}"/>

ok,dubbo协议,没有配序列化方式,那再来找一下dubbo默认的序列化方式。

首先找到了这个包:

Dubbo序列化-结合源码找问题

然后在Serialization接口(实现一些自定义序列化扩展用的)中发现了默认序列化的方式是hessian2:

Dubbo序列化-结合源码找问题

然后通过Hessian2Serialization的serialize方法和deserialize方法找到了Hessian2ObjectOutput、Hessian2ObjectInput这个两个类,之后通过里面的writeObject方法和readObject方法,找到了这两个类:JavaSerializer和JavaDeserializer。就是默认的序列化器和反序列化器。

首先我们来看序列化。构造方法:

Dubbo序列化-结合源码找问题

我们看看他干了个什么事:

  1. 首先检查了有没有writeReplace方法

  2. 然后把所有声明的字段放到数组中遍历,然后把除了transientstatic修饰的字段放到ArrayList中去

  3. 然后往上找父类执行相同操作

  4. 然后把所有符合条件的字段放到一个Field数组里面,先放基本数据类型,再放引用数据类型

  5. 最后把字段放入对应类型的序列化器中去,得到一个FieldSerializer序列化器数组

我们还是继续看writeObject方法:

Dubbo序列化-结合源码找问题

Dubbo序列化-结合源码找问题

主要是第二张图的3个方法,做的事情大概就是循环序列化field的名和值。

下面再来看看反序列化。构造方法:

Dubbo序列化-结合源码找问题

Dubbo序列化-结合源码找问题

这里大概做了3个事:

1、获取fieldMap,方法如下:

Dubbo序列化-结合源码找问题

2、获取readResolve方法

3、获取所有构造器

遍历构造器数组找到cost最小的最佳构造器,然后用最佳构造器进行构造,方法如下:

Dubbo序列化-结合源码找问题

先看构造器方法,基本数据类型的话返回包装类型,引用数据类型返回null。

主要我们来看获取fieldMap的时候。和序列化时相同,先取子类再取父类,本来以为到这就结束了,可是看到了一行校验:

 
   
   
 
  1. fieldMap.get(field.getName()) == null

如果父类的字段名和子类字段名相同,会跳过该循环,也就是说只会有子类的值,那为什么还会覆盖?

看最后一个 readMap方法:

Dubbo序列化-结合源码找问题

debug发现值被覆盖就是在这里操作的:

 
   
   
 
  1. deser.deserialize(in, obj);

Dubbo序列化-结合源码找问题

子类set过值以后,父类过来也会拿到子类的反序列化器,把子类的值覆盖掉。

最后,那为什么会到readMap这一步呢?

debug发现SerializerFactory拿到反序列化器后会执行一个readMap操作:

基本上就到这里了,最主要的原因还是readMap方法,并不是很多博文说的fieldMap。如果哪里有不对的地方欢迎指出、讨论以便及时修改。


DubboHome社区运维多年,专注于Dubbo技术分享交流,如果你对Dubbo感兴趣欢迎关注,会持续的输出关于Dubbo的一切。

最近推出终身学习系列,面试题系列,想要一起学习,了解具体面试答案及原理的同学,欢迎大家的加入知识星球,一起交流讨论。




以上是关于Dubbo序列化-结合源码找问题的主要内容,如果未能解决你的问题,请参考以下文章

dubbo源码实践-serialize层的例子

dubbo源码实践-serialize层的例子

深度Dubbo源码 - SPI的使用与好处

2020-03-28Dubbo源码杂谈

设计模式------从dubbo源码中学习观察者模式

dubbo源码:Google protocol buffer 序列化协议使用及接入