欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

在此做记录。