温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Dubbo还有这样的bug,你能忍?

发布时间:2020-08-01 07:13:07 来源:网络 阅读:417 作者:wx5d6cccb1cb158 栏目:编程语言

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

如果你对StackOverflowError有一定的了解,就可以知道出现这个问题的主要原因就是调用栈太深,比如常见的无限递归调用。那本文要介绍的Dubbo抛出的这个StackOverflowError又是什么原因呢?且往下看。

重现问题

话不多说,直入主题。这次碰到的StackOverflowError非常好重现,只需要如下简短的代码即可。需要注意的是这里调用的是com.alibaba.dubbo.common.json.JSON,而不是fastjson中的com.alibaba.fastjson.JSON

Dubbo还有这样的bug,你能忍?

Dubbo还有这样的bug,你能忍?

运行这段代码能得到如下异常:

Dubbo还有这样的bug,你能忍?

Dubbo还有这样的bug,你能忍?

分析原因

由这个异常堆栈信息,我们很容易知道在GenericJSONConverter中的第73行和129行之间出现了无限递归调用,打开dubbo源码并debug,发现在调用GenericJSONConverter中的writeValue()方法时,首先会判断需要序列化的对象的类型。当对象是如下类型时会特殊处理:

  1. 原生类型或者封装类型;

  2. JSONNode类型;

  3. 枚举;

  4. 数组;

  5. Map;

  6. 集合类型;

如果需要序列化的对象是其他类型,比如这里的Locale类型,序列化逻辑如下所示:

Dubbo还有这样的bug,你能忍?

Dubbo还有这样的bug,你能忍?

通过这段源码的分析,我们大概可以知道Locale的属性中肯定有Locale类型的属性。由于有Locale类型的属性,导致继续调用GenericJSONConverter中的writeValue()方法,从而无限递归下去,让我们继续Debug源码验证这个猜想。

Debug到String pns[] = w.getPropertyNames();,我们通过查看Locale的属性pns[]可以验证我们前面的猜想,如下图所示。Locale属性availableLocales的类型还是Locale,从而出现死循环直到抛出StackOverflowError:

Dubbo还有这样的bug,你能忍?

Dubbo还有这样的bug,你能忍?

解决问题

那么如何解决这个问题呢?很简单,不要使用dubbo中的JSON,改为使用fastjson中的JSON,或者jackson和GSON都可以:

Dubbo Fix

笔者翻看dubbo issue历史,发现dubbo在2018-05-09修复了这个问题,对应的dubbo版本是2.6.3,描述为:add Locale serialize & deserialize support。pull地址如下:https://github.com/apache/dubbo/pull/1761/commits。

修复的代码片段如下所示,主要改动点有:

  1. 如果序列化对象是Locale类型,那么序列化方式就是调用toString()方法;

  2. 如果反序列化目标对象类型是Locale,那么将value以下划线分割,然后构造Locale对象,用法参考:JSON.parse("zhCN", Locale.class);

Dubbo还有这样的bug,你能忍?

Dubbo还有这样的bug,你能忍?


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI