转载

StackOverflowError:根因竟然是Dubbo的锅!

前言

某天业务方的同事和我反馈,说系统出现了 StackOverflowError .坦白说, Exception 见得过了。但是 Error 倒是很少出现,此时他的心情是这样的:

一波猛如虎的操作

我们先来看血淋淋的案发现场

StackOverflowError:根因竟然是Dubbo的锅!

从异常栈中很明显发现出现了死循环,其实 StackOverflowError 绝大多数都是死循环、递归引起的。 那么,这为什么会出现循环调用呢?我们根据这个溢出的案发现场查看源码

StackOverflowError:根因竟然是Dubbo的锅!

如果你是用idea的话,他还会用图标提示你,这里会出现递归调用。

那么问题来了,这里究竟为什么会循环递归调用?由于这个问题是必然重现的,对于之前查看过我源码解析的老粉丝来说简直是 so easy .我们触发场景,然后把断点打在案发现场,不断把断点放过,反复几次之后,如下图

StackOverflowError:根因竟然是Dubbo的锅!

经过上面的数据,我们已经粗略看出死循环的迹象.我们把目标锁定在了 currencyavailableCurrencies . 为什么这里会出现反复的循环呢?我们查看一下 Currency 类的源码

1public static Set<Currency> getAvailableCurrencies() {
2
3 //省略...
4}

结合断点的序列化情况可以看出,currency进行json序列化的时候,需要去序列化 availableCurrencies .然后 getAvailableCurrencies() 又包含currency,从而陷入了死循环。

本地重现

话说能重现问题,就相当于问题解决了一半!接下来尝试在本地用很小的一段代码来重现这个问题:

StackOverflowError:根因竟然是Dubbo的锅!

 1public class FeiChaoDTO {
2
3 private Currency currency;
4
5 public Currency getCurrency() {
6 return currency;
7 }
8
9 public void setCurrency(Currency currency) {
10 this.currency = currency;
11 }
12}
1@Test
2public void test() throws Exception {
3 FeiChaoDTO feiChaoDTO = new FeiChaoDTO();
4 feiChaoDTO.setCurrency(Currency.getInstance("CNY"));
5 String json = JSON.json(feiChaoDTO);
6 System.out.println(json);
7}

如何解决

很明显,出现这个问题的原因是因为该同学用了Dubbo[ |ˈdʌbəʊ| ,发音为`打波 `] 里面的json序列化工具类,因为这个工具并非是Dubbo主流功能,所以关注度不足,自然存在一些不完善的功能,并且在Dubbo 2.6.x 以后版本,已经标注为过期.另外我们再看一下阿里开发手册

StackOverflowError:根因竟然是Dubbo的锅!

要解决这个问题方式很简单,既然要json序列化,那么就用主流的json序列化工具,无论是用 fastjsongsonjackson 都有对这些循环的情况做处理。还是那句话,本公众号已经和各大搜索引擎长期合作,按照我的描述搜索,比如 fastjson 循环引用 ,你想要的都有。当然细心的你可能发现,这些主流工具都不会去序列化 availableCurrencies 字段,Dubbo的这个序列化工具处理逻辑和主流的JSON工具处理还是有些不同。当然不用纠结,Dubbo本身定位就是RPC框架,JSON解析器还是建议选用上面三大神器中的一个。

【阿飞的博客】 公众号二维码

↓↓↓↓

StackOverflowError:根因竟然是Dubbo的锅!

原文  http://mp.weixin.qq.com/s?__biz=MzU5ODUwNzY1Nw==&mid=2247484736&idx=1&sn=3f95dbd3d092ec52990baa17e19efa0c
正文到此结束
Loading...