fastjson 相互引用的类示例,调用toJSON报堆栈溢出

t2a7ltrp  于 2021-11-27  发布在  Java
关注(0)|答案(2)|浏览(1009)

建了3个互相引用的类:Father、Mother、Son
public class Father {
private String name;
private Son son;
private Mother wife;

public static Father init() {
    Father father = new Father();
    father.name = "This is father";
    return father;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Son getSon() {
    return son;
}

public void setSon(Son son) {
    this.son = son;
}

public Mother getWife() {
    return wife;
}

public void setWife(Mother wife) {
    this.wife = wife;
}

}

public class Mother {
private String name;
private Son son;
private Father husband;

public static Mother init() {
    Mother mother = new Mother();
    mother.name = "This is mother";
    return mother;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Son getSon() {
    return son;
}

public void setSon(Son son) {
    this.son = son;
}

public Father getHusband() {
    return husband;
}

public void setHusband(Father husband) {
    this.husband = husband;
}

}

public class Son {
private String name;
private Mother mother;
private Father father;

public static Son init() {
    Son son = new Son();
    son.name = "This is son";
    return son;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Mother getMother() {
    return mother;
}

public void setMother(Mother mother) {
    this.mother = mother;
}

public Father getFather() {
    return father;
}

public void setFather(Father father) {
    this.father = father;
}

}

进行如下的测试:
Father father = Father.init();
Mother mother = Mother.init();
Son son = Son.init();
father.setWife(mother);
father.setSon(son);
mother.setHusband(father);
mother.setSon(son);
son.setFather(father);
son.setMother(mother);
JSONObject objectFather = (JSONObject) JSON.toJSON(father);

调用toJSON时堆栈溢出。
环境:1.2.62,jdk6

ddarikpa

ddarikpa1#

这个是堆栈信息
Exception in thread "main" java.lang.StackOverflowError at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at com.alibaba.fastjson.JSON.getMixInAnnotations(JSON.java:1282) at com.alibaba.fastjson.serializer.SerializeConfig.get(SerializeConfig.java:805) at com.alibaba.fastjson.serializer.SerializeConfig.getObjectWriter(SerializeConfig.java:440) at com.alibaba.fastjson.serializer.SerializeConfig.getObjectWriter(SerializeConfig.java:436) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1087) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095) at com.alibaba.fastjson.JSON.toJSON(JSON.java:1095)

上面出现最多就是JSON.java:1095,那就看看JSON.java的1095行到底是什么。

在这里用了个递归,那就在它上面打个断点看看它到底是怎么执行的。

`
@SuppressWarnings("unchecked")
public static Object toJSON(Object javaObject, SerializeConfig config) {
if (javaObject == null) {
return null;
}

if (javaObject instanceof JSON) {
        return javaObject;
    }

    if (javaObject instanceof Map) {
        Map<Object, Object> map = (Map<Object, Object>) javaObject;

        int size = map.size();

        Map innerMap;
        if (map instanceof LinkedHashMap) {
            innerMap = new LinkedHashMap(size);
        } else if (map instanceof TreeMap) {
            innerMap = new TreeMap();
        } else {
            innerMap = new HashMap(size);
        }

        JSONObject json = new JSONObject(innerMap);

        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            Object key = entry.getKey();
            String jsonKey = TypeUtils.castToString(key);
            Object jsonValue = toJSON(entry.getValue(), config);
            json.put(jsonKey, jsonValue);
        }

        return json;
    }

    if (javaObject instanceof Collection) {
        Collection<Object> collection = (Collection<Object>) javaObject;

        JSONArray array = new JSONArray(collection.size());

        for (Object item : collection) {
            Object jsonValue = toJSON(item, config);
            array.add(jsonValue);
        }

        return array;
    }

    if (javaObject instanceof JSONSerializable) {
        String json = JSON.toJSONString(javaObject);
        return JSON.parse(json);
    }

    Class<?> clazz = javaObject.getClass();

    if (clazz.isEnum()) {
        return ((Enum<?>) javaObject).name();
    }

    if (clazz.isArray()) {
        int len = Array.getLength(javaObject);

        JSONArray array = new JSONArray(len);

        for (int i = 0; i < len; ++i) {
            Object item = Array.get(javaObject, i);
            Object jsonValue = toJSON(item);
            array.add(jsonValue);
        }

        return array;
    }

    if (ParserConfig.isPrimitive2(clazz)) {
        return javaObject;
    }

    ObjectSerializer serializer = config.getObjectWriter(clazz);
    if (serializer instanceof JavaBeanSerializer) {
        JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) serializer;

        JSONObject json = new JSONObject();
        try {
            Map<String, Object> values = javaBeanSerializer.getFieldValuesMap(javaObject);
            for (Map.Entry<String, Object> entry : values.entrySet()) {
                json.put(entry.getKey(), toJSON(entry.getValue(), config));
            }
        } catch (Exception e) {
            throw new JSONException("toJSON error", e);
        }
        return json;
    }

    String text = JSON.toJSONString(javaObject);
    return JSON.parse(text);
}

`

这个是toJSON的完整方法。

第一次进来的是father对象,name属性put进去没毛病,接下来是son对象

然后又是father对象,又是son对象…… 堆栈就这样溢出了。

sc4hvdpw

sc4hvdpw2#

去掉 SerializerFeature.DisableCircularReferenceDetect

相关问题