性能文章>一次StackOverflowError排查,原因竟然和Dubbo有关!>

一次StackOverflowError排查,原因竟然和Dubbo有关!原创

1年前
7270111

前言

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

image.png

一波猛如虎的操作

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

image.png

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

image.png

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

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

image.png

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

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

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

本地重现

为了保证每个粉丝都能参与其中,肥朝抽取了一个必然重现的最简模型.希望肥朝公众号的粉丝都能一起参与进来,而不是每次看完分析过后,还有人一脸懵逼喊着666!

image.png

 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里面的json序列化工具类,因为这个工具并非是Dubbo主流功能,所以关注度不足,自然存在一些不完善的功能,并且在Dubbo2.6.x以后版本,已经标注为过期.另外我们再看一下阿里开发手册。

image.png

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

请先登录,再评论

欢迎关注我的微信公众号:【肥朝】

1年前

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问
Java多线程知识小抄集(一)
本文主要整理笔者遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。 1.interr