fastjson序列化出现StackOverflowError
今天在一个web项目里开发功能,记录日志用到了fastjson的序列化,把类型为RetreatRecord的数据对象序列化后打印出来。结果出现StackOverflowError。先贴出来异常堆栈:
Exception in thread "main" java.lang.StackOverflowError
at com.alibaba.fastjson.serializer.JSONSerializer.getContext(JSONSerializer.java:109)
at com.alibaba.fastjson.serializer.JavaBeanSerializer.writeReference(JavaBeanSerializer.java:251)
at Serializer_1.write1(Unknown Source)
at Serializer_1.write(Unknown Source)
at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:390)
//下面3行堆栈重复300多次
at Serializer_1.write1(Unknown Source)
at Serializer_1.write(Unknown Source)
at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:390)
经排查原因,发现派生类RetreatRecord继承自DataEntity,DataEntity里有一个User currentUser字段。User也派生自DataEntity。currentUser的get方法如下:
public User getCurrentUser() {
if(null==currentUser){
currentUser=new User();
}
return currentUser;
}
问题就出现在了currentUser为null时给其初始化的这句上。
debug程序可见,fastjson包里JSONSerializer.java的如下方法被死循环执行,直到堆栈溢出。
// D:\workspace\m3\com\alibaba\fastjson\1.2.6\fastjson-1.2.6-sources.jar!\com\alibaba\fastjson\serializer\JSONSerializer.java
public final void writeWithFieldName(Object object, Object fieldName, Type fieldType, int fieldFeatures) {
try {
if (object == null) {
out.writeNull();
return;
}
Class<?> clazz = object.getClass();
ObjectSerializer writer = getObjectWriter(clazz);
writer.write(this, object, fieldName, fieldType, fieldFeatures);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
分析:我们知道fastjson是基于流写入的。不难看出,在调用getCurrentUser时,因为currentUser是null,所以要给currentUser初始化,这时fastjson又要调用其getCurrentUser方法,然后又因为currentUser是null而不得不再给currentUser初始化,如此反复。。。,必然导致StackOverflow。
简化我遇到的情况,大家可以运行下面的代码来复现这个bug:
package fastjsonstackoverflow;
import java.io.Serializable;
public class MyEntity implements Serializable { String id;
MyEntity currentUser; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} /**
* 即使没有定义length字段,fastjson序列化不会出现异常
* @return
*/
public int getLength(){
return 0;
} public MyEntity getCurrentUser() {
if(null==currentUser){
currentUser=new MyEntity();
}
return currentUser;
} public void setCurrentUser(MyEntity currentUser) {
this.currentUser = currentUser;
}
} package fastjsonstackoverflow;
import com.alibaba.fastjson.JSONObject;
public class MainTest {
public static void main(String[] args) {
MyEntity entity = new MyEntity();
// System.out.println("mydata:"+entity.getCurrentUser());
System.out.println("mydata:" + JSONObject.toJSONString(entity));
}
}
ps:今天通过查看fastjson源码,了解到java中的移位运算符>> <<,
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
在此做记录。
fastjson序列化出现StackOverflowError的更多相关文章
- 用自定义注解实现fastjson序列化的扩展
这篇文章起源于项目中一个特殊的需求.由于目前的开发方式是前后端分离的,基本上是通过接口提供各个服务. 而前两天前端fe在开发中遇到了一些问题:他们在处理字符串类型的时间时会出现精度丢失的情况,所以希望 ...
- fastjson序列化排序问题
fastjson序列化,默认是用字母排序, 那么怎么来实现按照自己定义的顺序输出,想要的json串呢? 直接上代码: import com.alibaba.fastjson.annotation.JS ...
- FastJson序列化时过滤字段(属性)的方法总结
FastJson序列化时(即转成JSON字符串时),可以过滤掉部分字段,或者只保留部分字段,方法有很多,下面举一些常用的方法. 方法一.FastJson的注解 @JSONField(serialize ...
- Java基础/利用fastjson序列化对象为JSON
利用fastjson序列化对象为JSON 参考博客:http://blog.csdn.net/zeuskingzb/article/details/17468079 Step1:定义实体类 //用户类 ...
- FastJson序列化对象复杂时出错问题解决
FastJson序列化对象复杂时出错问题解决 针对复杂的对象,如Map<String, List<Map<String, XxxObject<A, B, C>>&g ...
- spring-data-redis注册fastjson序列化工具
使用spring-data-redis的时候,其序列化工具自带:
- FastJson序列化Json自定义返回字段,普通类从spring容器中获取bean
前言: 数据库的字段比如:price:1 ,返回需要price:1元. 这时两种途径修改: ① 比如sql中修改或者是在实体类转json前遍历修改. ②返回json,序列化时候修改.用到的是fastj ...
- FastJson 序列化与反序列化一些说明
最近所属的组需要对接一些征信结构,就涉及到很多中的数据格式,而springmvc中使用的是jackson作为@ResponseBody的依赖jar 但是个人认为fastkson的性能要高于jackso ...
- Fastjson 序列化,反序列化Map对象排序问题(字符串转map,map转字符串)
背景 记录项目中遇到的 关于fastjson jsonobject转string乱序,string转jsonObject乱序问题的解决方案 fastJson issues 问题来源描述参见: http ...
随机推荐
- react-native项目中集成react-native-camera插件
1. 安装 yarn add react-native-camera 2. 手动关联 (1)在AndroidManifest.xml中添加权限配置 <uses-permission androi ...
- sort it 树状数组+逆序对
sum[i]是1-i所有1的和,而i-sum[a[i]]就是在a[i]后面的数,即在i之前出现,却比他大的数.1是加在a[i]上,即i实际应该放的位置.而c[i]是为sum做准备的 #include& ...
- SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu
%SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu X = [16.4700 96.1000 16.4700 94.4400 20.0900 92.5400 2 ...
- JS变量重复声明以及忽略var 声明的问题及其背后的原理
腾讯的一个笔试题,先看一下 var a = 100; function fn() { alert(a); //undefined var a = 200; alert(a); //200 } fn() ...
- Pok 使用指南
Pok 使用指南 POK 是一个开源的符合ARINC653的操作系统,因为一些原因,我要开始接触一个全新的领域,再此希望记录下每天点滴进步,同时也欢迎指正吧. 目前先简单说明POK的使用指南 获取源码 ...
- PYQT窗口可视化编程
1.用PYQT的Qt设计师设计完程序UI后,将其转换为UI.py脚本. 转换步骤见帖:http://www.cnblogs.com/doudongchun/p/3694765.html 2.在同目录下 ...
- CentOS下 SVN版本控制的安装(包括yum与非yum)的步骤记录。
一.yum安装 rpm -qa subversion //检查是否安装了低版本的SVN yum remove subversion //如果存储旧版本,卸载旧版本SVN 开始安装 yum -y ins ...
- __http原理__HTTP 协议简介
HTTP 协议通信流程 超文本 除了文本以外,还有其他数据类型的内容 HTTP 协议 指计算机网络通信中 两台计算机之间所必须遵守的规定或规则 Hypertext Transport Protocol ...
- vue菜鸟从业记:没准备好的面试,那叫尬聊
最近我的朋友王小闰参加了一场面试,在他填写简历表的时候,排在他前面的应聘者正在旁边邻桌接受来自面试官的检验. 王小闰边写边想,这不就是一会儿要面试自己的前端leader么,现在面试官提问的一些面试题会 ...
- 遍历文件后缀名 为 .java的文件
import java.io.File; import java.io.FileFilter; //创建一个功夫类继承文件管理类 public class FileFu implements Fil ...