溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Dubbo還有這樣的bug,你能忍?

發(fā)布時間:2020-08-01 07:13:07 來源:網(wǎng)絡 閱讀:407 作者:wx5d6cccb1cb158 欄目:編程語言

本文場景基于dubbo-2.5.3版本。

如果你對StackOverflowError有一定的了解,就可以知道出現(xiàn)這個問題的主要原因就是調(diào)用棧太深,比如常見的無限遞歸調(diào)用。那本文要介紹的Dubbo拋出的這個StackOverflowError又是什么原因呢?且往下看。

重現(xiàn)問題

話不多說,直入主題。這次碰到的StackOverflowError非常好重現(xiàn),只需要如下簡短的代碼即可。需要注意的是這里調(diào)用的是com.alibaba.dubbo.common.json.JSON,而不是fastjson中的com.alibaba.fastjson.JSON

Dubbo還有這樣的bug,你能忍?

Dubbo還有這樣的bug,你能忍?

運行這段代碼能得到如下異常:

Dubbo還有這樣的bug,你能忍?

Dubbo還有這樣的bug,你能忍?

分析原因

由這個異常堆棧信息,我們很容易知道在GenericJSONConverter中的第73行和129行之間出現(xiàn)了無限遞歸調(diào)用,打開dubbo源碼并debug,發(fā)現(xiàn)在調(diào)用GenericJSONConverter中的writeValue()方法時,首先會判斷需要序列化的對象的類型。當對象是如下類型時會特殊處理:

  1. 原生類型或者封裝類型;

  2. JSONNode類型;

  3. 枚舉;

  4. 數(shù)組;

  5. Map;

  6. 集合類型;

如果需要序列化的對象是其他類型,比如這里的Locale類型,序列化邏輯如下所示:

Dubbo還有這樣的bug,你能忍?

Dubbo還有這樣的bug,你能忍?

通過這段源碼的分析,我們大概可以知道Locale的屬性中肯定有Locale類型的屬性。由于有Locale類型的屬性,導致繼續(xù)調(diào)用GenericJSONConverter中的writeValue()方法,從而無限遞歸下去,讓我們繼續(xù)Debug源碼驗證這個猜想。

Debug到String pns[] = w.getPropertyNames();,我們通過查看Locale的屬性pns[]可以驗證我們前面的猜想,如下圖所示。Locale屬性availableLocales的類型還是Locale,從而出現(xiàn)死循環(huán)直到拋出StackOverflowError:

Dubbo還有這樣的bug,你能忍?

Dubbo還有這樣的bug,你能忍?

解決問題

那么如何解決這個問題呢?很簡單,不要使用dubbo中的JSON,改為使用fastjson中的JSON,或者jackson和GSON都可以:

Dubbo Fix

筆者翻看dubbo issue歷史,發(fā)現(xiàn)dubbo在2018-05-09修復了這個問題,對應的dubbo版本是2.6.3,描述為:add Locale serialize & deserialize support。pull地址如下:https://github.com/apache/dubbo/pull/1761/commits。

修復的代碼片段如下所示,主要改動點有:

  1. 如果序列化對象是Locale類型,那么序列化方式就是調(diào)用toString()方法;

  2. 如果反序列化目標對象類型是Locale,那么將value以下劃線分割,然后構(gòu)造Locale對象,用法參考:JSON.parse("zhCN", Locale.class);

Dubbo還有這樣的bug,你能忍?

Dubbo還有這樣的bug,你能忍?


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI