瞭解dubbo序列化 從bug開始

    首先交代背景,前幾天遇到一個小bug,因爲其餘系統的一個DTO子類和父類有一個字段名重複了,因此致使我set的子類字段那邊拿不到值。改起來很簡單嘛,讓對面把子類的字段刪掉就好,可是拿不到值的緣由讓我想了好久,很明顯是序列化和反序列化的過程當中這個字段的值丟失了,可是究竟是在哪一步呢?仍是決定看看源碼給本身一個答案。java

dubbo版本:2.6.7


首先先肯定協議和序列化的方式:apache

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

ok,dubbo協議,沒有配序列化方式,那再來找一下dubbo默認的序列化方式:
首先找到了這個包:
clipboard.png數組

而後在Serialization接口(實現一些自定義序列化擴展用的)中發現了默認序列化的方式是hessian2spa

clipboard.png

而後經過Hessian2Serializationserialize方法和deserialize方法找到了Hessian2ObjectOutputHessian2ObjectInput這個兩個類,以後經過裏面的writeObject方法和readObject方法,找到了這兩個類:JavaSerializerJavaDeserializer。就是默認的序列化器和反序列化器。debug

首先咱們來看序列化:
構造方法:
clipboard.pngcode

咱們看看他幹了個什麼事
首先檢查了有沒有writeReplace方法
而後把全部聲明的字段放到數組中遍歷,而後把除了transientstatic修飾的字段放到ArrayList中去
而後往上找父類執行相同操做
而後把全部符合條件的字段放到一個Field數組裏面,先放基本數據類型,再放引用數據類型
最後把字段放入對應類型的序列化器中去
獲得一個FieldSerializer序列化器數組xml

咱們仍是繼續看writeObject方法接口

clipboard.png

clipboard.png

主要是第二張圖的3個方法,作的事情大概就是循環序列化field的名和值ip


下面再來看看反序列化:
構造方法:文檔

clipboard.png

clipboard.png

這裏大概作了3個事
獲取fieldMap,方法以下:

clipboard.png

獲取readResolve方法
獲取全部構造器
遍歷構造器數組找到cost最小的最佳構造器
而後用最佳構造器進行構造,方法以下:
clipboard.png

先看構造器方法,基本數據類型的話返回包裝類型,引用數據類型返回null

主要咱們來看獲取fieldMap的時候。和序列化時相同,先取子類再取父類,原本覺得到這就結束了,但是看到了一行校驗

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

若是父類的字段名和子類字段名相同,會跳過該循環,也就是說只會有子類的值,那爲何還會覆蓋?
看最後一個readMap方法:

clipboard.png

debug發現值被覆蓋就是在這裏操做的

deser.deserialize(in, obj);

clipboard.png

子類set過值之後,父類過來也會拿到子類的反序列化器,把子類的值覆蓋掉。

最後,那爲何會到readMap這一步呢?

debug發現SerializerFactory拿到反序列化器後會執行一個readMap操做

clipboard.png

基本上就到這裏了,最主要的緣由仍是readMap方法,並非不少博文說的fieldMap。若是哪裏有不對的地方歡迎指出、討論以便及時修改。

參考文檔:連接描述

相關文章
相關標籤/搜索