1. 程式人生 > >java物件序列化技術

java物件序列化技術

一、簡介

序列化用於儲存或傳輸物件的資訊。java的API提供了序列換技術,使用簡單,但往往空間佔用大。

Kryo是一個java物件的序列化框架。它的目標是序列化更快、序列化物件更小、簡單易用的API。Kryo可以將物件持久化到檔案、資料庫、或則用於網路傳輸。Kryo可以進行自動深度和淺層複製/克隆,它是直接將一個物件複製到另一個物件,而不是將物件轉成bytes再轉成物件。

protobuf是google開源的一種rpc協議,它比xml格式的訊息更小、更快、更少歧義,但是比xml的可讀性差,由於訊息按一定格式序列化,如果兩端的訊息比對不上,即便是抓到包也很難分析出訊息的原文。它提供了自己的物件序列化方式,並且支援多語言。

二、java序列化與反序列化

package com.sunq.serializers.java;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import com.sunq.serializers.BObject;

public class TestJava {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
	long l1 = System.currentTimeMillis();
	BObject bo = new BObject();
	bo.setS1("aaaaaaaaaa");
	bo.setS10("bbbbbbbbbb");
	bo.setS2("cccccccccc");
	bo.setS3("dddddddddd");
	bo.setS4("eeeeeeeeee");
	bo.setS5("ffffffffff");
	bo.setS6("gggggggggg");
	bo.setS7("hhhhhhhhhh");
	bo.setS8("iiiiiiiiii");
	bo.setS9("jjjjjjjjjj");
	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object_java.bin"));
	oos.writeObject(bo);
    oos.flush();
	oos.close();
	long l2 = System.currentTimeMillis();
	System.out.println("serialize time:" + (l2-l1)+ "ms.");
	ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object_java.bin"));
	Object o = ois.readObject();
	ois.close();
	long l3 = System.currentTimeMillis();
	System.out.println("deserialize time:" +(l3-l2) + "ms.");
	System.out.println(o.toString());
}
}

執行結果,序列化耗時大概在10ms左右,反序列化耗時在65ms左右,空間佔用296位元組。

三、kryo序列化與反序列化

package com.sunq.serializers.kryo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.sunq.serializers.AObject;

public class TestKryo {
public static void main(String[] args) throws FileNotFoundException {
	Kryo kryo = new Kryo();
	kryo.register(AObject.class);
	AObject ao = new AObject();
	ao.setS1("aaaaaaaaaa");
	ao.setS10("bbbbbbbbbb");
	ao.setS2("cccccccccc");
	ao.setS3("dddddddddd");
	ao.setS4("eeeeeeeeee");
	ao.setS5("ffffffffff");
	ao.setS6("gggggggggg");
	ao.setS7("hhhhhhhhhh");
	ao.setS8("iiiiiiiiii");
	ao.setS9("jjjjjjjjjj");
	Output out = new Output(new FileOutputStream("object_kryo.bin"));
	kryo.writeObject(out, ao);
	out.close();
	Input in = new Input(new FileInputStream("object_kryo.bin"));
	AObject aob = kryo.readObject(in, AObject.class);
	in.close();
	System.out.println(aob.toString());
}
}

序列化耗時200ms左右,反序列化耗時14ms左右,空間佔用111位元組。

四、protobuf序列化與反序列化

package com.sunq.serializers.proto;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.sunq.serializers.AObjectProc;

public class TestProto {
public static void main(String[] args) throws IOException {
	long l1 = System.currentTimeMillis();
	AObjectProc.AObject.Builder builder = AObjectProc.AObject.newBuilder();
	builder.setS1("aaaaaaaaaa");
	builder.setS10("bbbbbbbbbb");
	builder.setS2("cccccccccc");
	builder.setS3("dddddddddd");
	builder.setS4("eeeeeeeeee");
	builder.setS5("ffffffffff");
	builder.setS6("gggggggggg");
	builder.setS7("hhhhhhhhhh");
	builder.setS8("iiiiiiiiii");
	builder.setS9("jjjjjjjjjj");
	AObjectProc.AObject aob = builder.build();
	OutputStream os = new FileOutputStream("object_proc.bin");
	aob.writeTo(os);
	os.flush();
	os.close();
	long l2 = System.currentTimeMillis();
	System.out.println("serialize time:" + (l2-l1)+ "ms.");
	InputStream in = new FileInputStream("object_proc.bin");
	AObjectProc.AObject aob1 = AObjectProc.AObject.parseFrom(in);
	in.close();
	long l3 = System.currentTimeMillis();
	System.out.println("deserialize time:" +(l3-l2) + "ms.");
	System.out.println(aob1.toString());
}
}

序列化耗時85ms左右,反序列化耗時5ms左右,空間佔用120位元組。

五、比較

java的序列化優勢在於簡單,序列化快;缺點是反序列化解析慢,而且序列化後的資訊佔用空間較大。

kryo的序列化優勢在與簡單,反序列化解析較快,序列化後的資訊佔用空間很小;缺點是序列化較慢。

protobuf的序列化優勢在於,序列化較快,反序列化很快,佔用空間較小;缺點是生產序列化物件麻煩,語義麻煩。

不同的序列化方式各有優勢。