前言
某天業務方的同事和我反饋,說系統出現了StackOverflowError
.坦白說,Exception
見得過了,但是Error
倒是很少出現,此時他的心情是這樣的
一波猛如虎的操作
我們先來看血淋淋的案發現場
從異常棧中很明顯發現出現了死迴圈,其實StackOverflowError
絕大多數都是死迴圈、遞迴引起的.那麼,這為什麼會出現迴圈呼叫呢?我們根據這個溢位的案發現場檢視原始碼
如果你是用idea的話,他還會用圖示提示你,這裡會出現遞迴呼叫.
那麼問題來了,這裡究竟為什麼會迴圈遞迴呼叫?由於這個問題,是必然重現的,對於之前檢視過我原始碼解析的老粉絲來說簡直是so easy
.我們觸發場景,然後把斷點打在案發現場,不斷把斷點放過,反覆幾次之後,如下圖
經過上面的資料,我們已經粗略看出死迴圈的跡象.我們把目標鎖定在了currency
和availableCurrencies
. 為什麼這裡會出現反覆的迴圈呢?我們檢視一下Currency
類的原始碼
public static Set<Currency> getAvailableCurrencies() {
//省略...
}
複製程式碼
結合斷點的序列化情況可以看出,currency進行json序列化的時候,需要去序列化availableCurrencies
.然後getAvailableCurrencies()
又包含currency,從而陷入了死迴圈.
本地重現
為了保證每個粉絲都能參與其中,肥朝抽取了一個必然重現的最簡模型.希望肥朝公眾號的粉絲都能一起參與進來,而不是每次看完分析過後,還有人一臉懵逼喊著666
!
public class FeiChaoDTO {
private Currency currency;
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
}
複製程式碼
@Test
public void test() throws Exception {
FeiChaoDTO feiChaoDTO = new FeiChaoDTO();
feiChaoDTO.setCurrency(Currency.getInstance("CNY"));
String json = JSON.json(feiChaoDTO);
System.out.println(json);
}
複製程式碼
如何解決
很明顯,出現這個問題的原因是因為該同學用了Dubbo裡面的json序列化工具類,因為這個工具並非是Dubbo主流功能,所以關注度不足,自然存在一些不完善的功能,並且在Dubbo2.6.x
以後版本,已經標註為過期.另外我們再看一下阿里開發手冊
要解決這個問題方式很簡單,既然要json序列化,那麼就用主流的json序列化工具,無論是用fastjson
、gson
、jackson
都有對這些迴圈的情況做處理,還是那句話,本公眾號已經和各大搜尋引擎長期合作,按照我的描述搜尋,比如fastjson 迴圈引用
,你想要的都有.當然細心的你可能發現,這些主流工具都不會去序列化availableCurrencies
欄位,Dubbo的這個序列化工具處理邏輯和主流的JSON工具處理還是有些不同,當然不用糾結,Dubbo本身定位就是RPC框架,就像肥朝公眾號定位就是原始碼解析
、真實場景原始碼實戰
,JSON解析我們可以選用上面的三大神器中的一個.
寫在最後
近日有粉絲和肥朝反饋在面試過程遇到了如下的問題
我只想說,人家不問你也可以主動嘛.如果你是肥朝的粉絲,在工作、學習上遇到了什麼問題,歡迎來撩,只要你主動,我們的故事就開始了!
肥朝 是一個專注於 原理、原始碼、開發技巧的技術公眾號,號內原創專題式原始碼解析、真實場景原始碼原理實戰(重點)。掃描下面二維碼關注肥朝,讓本該造火箭的你,不再擰螺絲!