专业IT网络知识平台,分享IT百科知识、生活百科知识解答!

易企推科技
易企推科技

StackOverflowError原因,StackOverflowError解决办法

来源:小易整编  作者:小易  发布时间:2023-02-14 07:00
摘要:StackOverflowError原因,StackOverflowError解决办法如果你对StackOverflowError有一定的了解,就可以知道出现这个问题的主要原因就是调用栈太深,比如常见的无限递归调用。那本文要介绍的Dubbo...

StackOverflowError原因,StackOverflowError解决办法

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

StackOverflowError原因,StackOverflowError解决办法~noop

StackOverflowError重现问题

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

package com.afei.test.dubbo.provider.main;
import com.alibaba.dubbo.common.json.JSON;
import java.util.Locale;
public class DubboTest {
 public static void main(String[] args) throws Exception {
 Locale locale = Locale.getDefault();
 System.out.println(JSON.json(locale));
 }
}

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

Exception in thread "main" java.lang.StackOverflowError 

at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) 

at sun.util.locale.provider.LocaleResources.getLocaleName(LocaleResources.java:233)

at java.util.Locale.getDisplayName(Locale.java:1879) 

at java.util.Locale.getDisplayName(Locale.java:1845) 

at com.alibaba.dubbo.common.bytecode.Wrapper0.getPropertyValue(Wrapper0.java)

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:125)

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:73) 

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:129) 

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:73) 

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:129) 

at com.alibaba.dubbo.common.json.GenericJSONConverter.writeValue(GenericJSONConverter.java:73) ... ...

StackOverflowError分析原因

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

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

  2. JSONNode类型;

  3. 枚举;

  4. 数组;

  5. Map;

  6. 集合类型;

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

jb.objectBegin();
Wrapper w = Wrapper.getWrapper(c);
// 得到这个对象的所有属性
String pns[] = w.getPropertyNames();
// 遍历属性
for( String pn : pns )
{
 // 被序列化的对象Locale并不是Throwable类型,忽略这段逻辑
 if ((obj instanceof Throwable) && (
 "localizedMessage".equals(pn) 
 || "cause".equals(pn) 
 || "stackTrace".equals(pn))) {
 continue;
 }
 jb.objectItem(pn);
 // 得到当前遍历属性的值
 Object value = w.getPropertyValue(obj,pn);
 if( value == null || value == obj)
 jb.valueNull();
 else
 // 无限递归死循环出现在这里
 writeValue(value, jb, writeClass);
}

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

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

StackOverflowError原因,StackOverflowError解决办法

Locale中有Locale类型的属性

StackOverflowError解决问题

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

Locale locale = Locale.getDefault();
System.out.println(com.alibaba.fastjson.JSON.toJSON(locale));
System.out.println(new com.google.gson.Gson().toJson(locale));

本文地址:IT百科频道 https://www.hkm168.com/tags/903077.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


IT百科
小编:小易整编
相关文章相关阅读
  • 有没有录制电脑屏幕的方法

    有没有录制电脑屏幕的方法

    电脑屏幕有录制的方法吗有两个方法一是用win10电脑自带的录屏软件来录,打游戏的时候按一下【win+g】就行了二是用其他的录制软件来录制,比如“迅捷屏幕录像工具”,操作方法如下:1、首先在电脑上将这个工具下载下来。下载完成后打开工具,主页...

  • 电脑打不开视频是啥原因

    电脑打不开视频是啥原因

    电脑打不开视频可能是因为视频文件没有下载完成、没有支持此视频的播放器、视频文件后缀被修改过、视频文件关联不正确、视频文件在指定的网站才能打开、视频文件被损坏、软件问题、硬件问题、病毒感染、缺少必要的解码器和网络问题。详细介绍:1、视频文件没...

  • win7硬件加速设置方法

    win7硬件加速设置方法

    有很多网民在玩一些游戏或运行一些大软件,下载大文件,可能会觉得系统运行不够无忧无虑,这次可以尝试加速硬件。下面的小边将为您介绍如何设置win7的硬件加速方法。1.右击桌面空白处,然后点击右键菜单中的屏幕分辨率选项。2.进入电脑屏幕分辨率设置...

  • 迅雷下载速度慢怎么办-迅雷下载速度慢解决方法

    迅雷下载速度慢怎么办-迅雷下载速度慢解决方法

    迅雷下载速度慢怎么办?迅雷是目前国内用户使用最多的高速下载工具,其速度和效率都是同类下载工具的顶点,但是很多用户在使用的时候却发现迅雷的下载速度很慢,这其实是因为多个不同的问题导致的,那么我们该如何解决呢?下面就由小编为大家带来迅雷下载速度...

  • java中tostring方法的作用是什么

    java中tostring方法的作用是什么

    java中tostring方法的作用是会返回一个【以文本方式表示】此对象的字符串,结果是一个简明但易于读懂的信息表达式。java中tostring方法的作用是toString方法会返回一个“以文本方式表示”此对象的字符串。结果是一个简明但易...

  • 电脑运行内存怎么扩大 秒懂:电脑内存扩大内存的方法

    电脑运行内存怎么扩大 秒懂:电脑内存扩大内存的方法

    电脑运行内存怎么扩大?这是许多电脑用户常常遇到的问题。想要提升电脑运行速度和性能,扩大内存是一个有效的方法。但是,如何扩大内存呢?在本文中,php小编西瓜将为你介绍一些简单又实用的方法,让你秒懂如何扩大电脑内存,提升电脑的运行效率。无论你是...

  • 修复 Windows 11 中 Sxstrace.exe 运行时错误的 5 种方法

    修复 Windows 11 中 Sxstrace.exe 运行时错误的 5 种方法

    windows用户有时会发现启动程序很困难,在这种情况下可能会收到一条错误消息,要求使用命令行sxstrace.exe工具了解更多详细信息。sxstrace.exe由Microsoft于2006年11月首次为Windo...

  • CSS颜色设置方法:HEX、RGB、HSL的简单对比

    CSS颜色设置方法:HEX、RGB、HSL的简单对比

    css中,颜色值有多种表示方法,例如颜色名、十六进制颜色、rgb()、hex()、hsl()等等。那你知道hex、rgb和hsl之间有什么区别吗?下面本篇文章就来给大家简单对比一下hex、rgb、hsl,看看它们区别。不知道你是否了解HE...

  • 周排行
  • 月排行
  • 年排行

精彩推荐