fastjson序列化出现*Error
程序员文章站
2022-09-04 14:03:14
我们知道fastjson是基于流写入的。不难看出,在调用getCurrentUser时,因为currentUser是null,所以要给currentUser初始化,这时fastjson又要调用其getCurrentUser方法,然后又因为currentUser是null而不得不再给currentUs... ......
今天在一个web项目里开发功能,记录日志用到了fastjson的序列化,把类型为retreatrecord的数据对象序列化后打印出来。结果出现*error。先贴出来异常堆栈:
exception in thread "main" java.lang.*error 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初始化,如此反复。。。,必然导致*。
简化我遇到的情况,大家可以运行下面的代码来复现这个bug:
package fastjson*; 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 fastjson*; 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
在此做记录。
上一篇: Spring-全局异常拦截
推荐阅读
-
FastJson序列化自定义返回字段,普通类从spring容器中获取bean
-
fastjson序列化出现*Error
-
SpringDataJpa在一对多、多对多关系映射时出现*Error
-
hibernate多对一关联映射出现的java.lang.*Error问题
-
spark出现task不能序列化错误的解决方法 org.apache.spark.SparkException: Task not serializable
-
com.alibaba.fastjson 序列化 反序列
-
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
-
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
-
.NET高级代码审计(第三课)Fastjson反序列化漏洞
-
反序列化漏洞例子——fastjson反序列化漏洞的调试与分析