Junhc

岂止于博客

序列化

protobuf
  1. 结构化数据存储格式(json,xml等)
  2. 高性能编解码技术
  3. 语言和平台无关,扩展性好
  4. 支持java,C++,Python三种语言

优点:无需静态编译,但序列化前需预先传入schema
缺点:不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值

thrift
  1. 支持多种语言(C++,C#,Cocoa,Erlag,Haskell,java,Ocami,Perl,PHP,Python,Ruby,和SmallTalk)
  2. 适用了组建大型数据交换及存储工具,对于大型系统中的内部数据传输,相对于json和xml在性能上和传输大小上都有明显的优势。
  3. 支持三种比较典型的编码方式。(通用二进制编码,压缩二进制编码,优化的可选字段压缩编解码)
kryo

优点:速度快,序列化后体积小
缺点:跨语言支持较复杂

hessian

优点:默认支持跨语言
缺点:较慢

public byte[] serialize(Object obj) {
  Hessian2Output hos;
  try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
      hos = new Hessian2Output(bos);
      hos.writeObject(obj);
      hos.flush();
      return bos.toByteArray();
  } catch (IOException e) {
  }
  return null;
}

public <T> T deserialize(byte[] bytes) {
  ByteArrayInputStream bis;
  try {
      bis = new ByteArrayInputStream(bytes);
      Hessian2Input his = new Hessian2Input(bis);
      return (T) his.readObject();
  } catch (IOException e) {
  }
  return null;
}
fst

优点:fst是完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍,大小是JDK大小的1/3左右

<dependency>  
  <groupId>de.ruedigermoeller</groupId>  
  <artifactId>fst</artifactId>  
  <version>2.04</version>  
</dependency>
private static FSTConfiguration configuration = FSTConfiguration.createStructConfiguration();  

public static byte[] serialize(Object obj) {  
 return configuration.asByteArray(obj);  
}  

public static <T> T deserialize(byte[] bytes) {  
 return (T)configuration.asObject(bytes);  
}  
json
java
  1. 无法跨语言。这应该是java序列化最致命的问题了。由于java序列化是java内部私有的协议,其他语言不支持,导致别的语言无法反序列化,这严重阻碍了它的应用。
  2. 序列后的码流太大。java序列化的大小是二进制编码的5倍多!
  3. 序列化性能太低。java序列化的性能只有二进制编码的6.17倍,可见java序列化性能实在太差了。
public static byte[] serialize(Object obj) {  
  try (ByteArrayOutputStream baos = new ByteArrayOutputStream();  
          ObjectOutputStream oos = new ObjectOutputStream(baos);) {  
      oos.writeObject(obj);  
      return baos.toByteArray();  
  } catch (IOException e) {  
  }
  return null;
}  

public static <T> T deserialize(byte[] bytes) {  
  try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);  
          ObjectInputStream ois = new ObjectInputStream(bis);) {  
      return (T)ois.readObject();  
  } catch (Exception e) {  
  }
  return null;  
}  
Objenesis不使用构造方法创建Java对象
<dependency>
    <groupId>org.objenesis</groupId>
    <artifactId>objenesis</artifactId>
    <version>3.0.1</version>
</dependency>
public class T {
  private String id = "T";
  private String name;

  public T(String name) {
      this.name = name;
  }

  public String getId() {
      return id;
  }

  public String getName() {
      return name;
  }

  public static void main(String[] args) {
      // 第一种方式
      try {
          T t0 = T.class.newInstance();
          System.out.println(t0.getId());
      } catch (Exception e) {
          System.err.println("没有无参构造方法,无法实例化,抛异常");
      }
      // 第二种方式,不使用构造方法,对象以非标准的方式被动态实例化
      Objenesis objenesis = new ObjenesisStd();
      T t1 = objenesis.newInstance(T.class);
      // 属性的默认值获取不到
      System.out.println(t1.getId());
      // null
  }
}