一次StackOverflowError排查 stackoverflowerror

前言
某天业务方的同事和我反馈,说系统出现了StackOverflowError.坦白说,Exception见得过了,但是Error倒是很少出现,此时他的心情是这样的
一波猛如虎的操作
我们先来看血淋淋的案发现场
从异常栈中很明显发现出现了死循环,其实StackOverflowError绝大多数都是死循环、递归引起的.那么,这为什么会出现循环调用呢?我们根据这个溢出的案发现场查看源码
如果你是用idea的话,他还会用图标提示你,这里会出现递归调用.
那么问题来了,这里究竟为什么会循环递归调用?由于这个问题,是必然重现的,对于之前查看过我源码解析的老粉丝来说简直是so easy.我们触发场景,然后把断点打在案发现场,不断把断点放过,反复几次之后,如下图
【一次StackOverflowError排查 stackoverflowerror】经过上面的数据,我们已经粗略看出死循环的迹象.我们把目标锁定在了currency和availableCurrencies. 为什么这里会出现反复的循环呢?我们查看一下Currency类的源码
1publicstaticSet<Currency>getAvailableCurrencies(){23//省略...4} 结合断点的序列化情况可以看出,currency进行json序列化的时候,需要去序列化availableCurrencies.然后getAvailableCurrencies()又包含currency,从而陷入了死循环.
本地重现
为了保证每个粉丝都能参与其中,肥朝抽取了一个必然重现的最简模型.希望肥朝公众号的粉丝都能一起参与进来,而不是每次看完分析过后,还有人一脸懵逼喊着666!
1publicclassFeiChaoDTO{23privateCurrencycurrency;45publicCurrencygetCurrency(){6returncurrency;7}89publicvoidsetCurrency(Currencycurrency){10this.currency=currency;11}12} 1@Test2publicvoidtest()throwsException{3FeiChaoDTOfeiChaoDTO=newFeiChaoDTO();4feiChaoDTO.setCurrency(Currency.getInstance("CNY"));5Stringjson=JSON.json(feiChaoDTO);6System.out.println(json);7} 如何解决
很明显,出现这个问题的原因是因为该同学用了Dubbo里面的json序列化工具类,因为这个工具并非是Dubbo主流功能,所以关注度不足,自然存在一些不完善的功能,并且在Dubbo2.6.x以后版本,已经标注为过期.另外我们再看一下阿里开发手册
要解决这个问题方式很简单,既然要json序列化,那么就用主流的json序列化工具,无论是用fastjson、gson、jackson都有对这些循环的情况做处理,还是那句话,本公众号已经和各大搜索引擎长期合作,按照我的描述搜索,比如fastjson 循环引用,你想要的都有.当然细心的你可能发现,这些主流工具都不会去序列化availableCurrencies字段,Dubbo的这个序列化工具处理逻辑和主流的JSON工具处理还是有些不同,当然不用纠结,Dubbo本身定位就是RPC框架,就像肥朝公众号定位就是源码解析、真实场景源码实战,JSON解析我们可以选用上面的三大神器中的一个.
stackoverflowerror

    -- 展开阅读全文 --

      推荐阅读