您好,登錄后才能下訂單哦!
本文場景基于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,你能忍?
分析原因
由這個異常堆棧信息,我們很容易知道在GenericJSONConverter中的第73行和129行之間出現(xiàn)了無限遞歸調(diào)用,打開dubbo源碼并debug,發(fā)現(xiàn)在調(diào)用GenericJSONConverter中的writeValue()方法時,首先會判斷需要序列化的對象的類型。當對象是如下類型時會特殊處理:
原生類型或者封裝類型;
JSONNode類型;
枚舉;
數(shù)組;
Map;
集合類型;
如果需要序列化的對象是其他類型,比如這里的Locale類型,序列化邏輯如下所示:
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中的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。
修復的代碼片段如下所示,主要改動點有:
如果序列化對象是Locale類型,那么序列化方式就是調(diào)用toString()方法;
如果反序列化目標對象類型是Locale,那么將value以下劃線分割,然后構(gòu)造Locale對象,用法參考:JSON.parse("zhCN", Locale.class);
Dubbo還有這樣的bug,你能忍?
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。