• 对象序列化机制:允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
  • 序列化操作的对象需要实现Serializable或Externalizable,并且其内部所有属性也必须是可序列化的(String和StringBuilder类已实现了Serializable,基本数据类型默认可序列化),因为static和transient修饰的成员变量,不会被操作,所以不能序列化。
  • 一般都是把对象转为josn格式进行序列化

自定义类举例:

  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. import java.io.Serializable;
  5. @NoArgsConstructor
  6. @AllArgsConstructor
  7. @Data
  8. public class Ahzoo implements Serializable {//需要将类实现Serializable或Externalizable才能进行对象的序列化操作
  9. // 实现Serializable接口后,需要提供一个long类型的全局常量,值可以任意数,但是必须声明,反序列时会进行对比,如果serialVersionUID一致,会认为是一致的,否则就会报序列号不一致的异常
  10. public static final long serialVersionUID = 7777777L;{
  11. private Integer age;
  12. private String name;
  13. private Account account;
  14. }
  15. class Account implements Serializable{//Account作为Person类的属性,也必须是可进行序列化的才行
  16. public static final long serialVersionUID = 999999999L;
  17. int id;
  18. public Account(int id){
  19. this.id = id;
  20. }
  21. }

FastJSON

引入依赖:

  1. <!-- json与对象互转-->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>fastjson</artifactId>
  5. <version>1.2.49</version>
  6. </dependency>

测试使用:

  1. import org.junit.Test;
  2. import com.alibaba.fastjson.JSON;
  3. public class MethodTest {
  4. @Test
  5. public void toTest {
  6. //转成json字符串
  7. String json = JSON.toJSONString(new StringBuilder("ahzoo"));
  8. System.out.println(json);
  9. //转成(StringBuilder)对象
  10. StringBuilder str = JSON.parseObject(json,StringBuilder.class);
  11. System.out.println(str);
  12. //转成(StringBuilder)列表
  13. List<StringBuilder> = JSONObject.parseObject(json, new TypeReference<List<StringBuilder>>() {
  14. });
  15. //转为Map
  16. List<Map<String, Object>> listMap = JSON.parseObject(json, new TypeReference<List<Map<String,Object>>>(){});
  17. }

Jackson

  1. <dependency>
  2. <groupId>com.fasterxml.jackson.core</groupId>
  3. <artifactId>jackson-databind</artifactId>
  4. <version>2.9.7</version>
  5. </dependency>

测试使用:

  1. import org.junit.Test;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. public class MethodTest {
  4. @Test
  5. public void toTest {
  6. ObjectMapper objectMapper = new ObjectMapper();
  7. try {
  8. //转为JSON
  9. String json = objectMapper.writeValueAsString(new StringBuilder("ahzoo"));
  10. //转为对象
  11. StringBuilder str = objectMapper.readValue(json, StringBuilder.class);
  12. //转为List
  13. List<StringBuilder> = objectMapper.readValue(fileString, new TypeReference<List<StringBuilder>>() {
  14. });
  15. } catch (JsonProcessingException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. }

Gson

  1. <dependency>
  2. <groupId>com.google.code.gson</groupId>
  3. <artifactId>gson</artifactId>
  4. <version>2.8.5</version>
  5. </dependency>

测试使用:

  1. import com.google.gson.Gson;
  2. import org.junit.Test;
  3. public class MethodTest {
  4. @Test
  5. public void toTest {
  6. //转成json字符串
  7. Gson gson = new Gson();
  8. String json = gson.toJson(new StringBuilder("ahzoo"));
  9. System.out.println(json);
  10. //json字符串转成对象
  11. StringBuilder str = gson.fromJson(json,StringBuilder.class);
  12. System.out.println(str);
  13. //转为list
  14. List<StringBuilder> list = gson.fromJson(json, new TypeToken<List<StringBuilder.class>>() {
  15. }.getType());
  16. }
  17. }

后记

  • 使用FastJSON序列化时,栈内存溢出:
    1. java.lang.StackOverflowError: null
    2. at org.nustaq.serialization.FSTObjectInput$2.readObjectOverride(FSTObjectInput.java:1030)
    3. at java.io.ObjectInputStream.readObject(ObjectInputStream.java:365)
    4. at org.nustaq.serialization.FSTObjectInput$MyObjectStream.readObjectOverride(FSTObjectInput.java:1353)
    5. at java.io.ObjectInputStream.readObject(ObjectInputStream.java:365)
    6. at java.util.HashMap.readObject(HashMap.java:1396)
    7. at sun.reflect.GeneratedMethodAccessor174.invoke(Unknown Source)
    8. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    9. at java.lang.reflect.Method.invoke(Method.java:498)
    10. at org.nustaq.serialization.FSTObjectInput.readObjectCompatibleRecursive(FSTObjectInput.java:609)
    11. at org.nustaq.serialization.FSTObjectInput.readObjectCompatibleRecursive(FSTObjectInput.java:598)
    12. at org.nustaq.serialization.FSTObjectInput.readObjectCompatibleRecursive(FSTObjectInput.java:598)
    13. at org.nustaq.serialization.FSTObjectInput.readObjectCompatible(FSTObjectInput.java:574)
    14. at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:559)
    15. at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:374)
    16. at org.nustaq.serialization.FSTObjectInput.readObjectFields(FSTObjectInput.java:713)
    17. at org.nustaq.serialization.FSTObjectInput.instantiateAndReadNoSer(FSTObjectInput.java:566)
    18. at org.nustaq.serialization.FSTObjectInput.readObjectWithHeader(FSTObjectInput.java:374)
    19. at org.nustaq.serialization.FSTObjectInput.readObjectInternal(FSTObjectInput.java:331)
    20. at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:311)
    21. at org.nustaq.serialization.FSTObjectInput.readObject(FSTObjectInput.java:245)
    22. at org.nustaq.serialization.FSTConfiguration.asObject(FSTConfiguration.java:1158)
    23. at com.jeesite.common.lang.ObjectUtils.unserializeFst(ObjectUtils.java:242)
    24. at com.jeesite.common.lang.ObjectUtils.cloneBean(ObjectUtils.java:259)
    25. at com.jeesite.common.entity.BaseEntity.clone(dk:489)
    26. at com.jeesite.modules.sys.utils.UserUtils.get(nd:7)
    27. at com.jeesite.modules.sys.utils.UserUtils.getUser(nd:396)
    28. at com.jeesite.common.entity.BaseEntity.getCurrentUser(dk:542)
    29. at com.alibaba.fastjson.serializer.ASMSerializer_2_User.write(Unknown Source)
    原因:需要被反序列化的实体类继承了一个类(DataEntity),该类中的一个递归方法陷入了死循环,最终导致栈内存溢出
    Snipaste_2021-11-15_15-22-59.png
    经过多方调试后发现,类(DataEntity)中的(getCurrentUser())方法的currentUser属性在递归中一直都是null,最终导致栈内存溢出。
    (我的)解决方法:将FastJSON替换为Jackson;
    替换后再次调试,发现currentUser属性被成功赋值

Snipaste_2021-11-15_16-02-42.png