下面介绍几种常用的Java序列化技术,耗时比较,单位纳秒
0.002511:com.my.tools.serialize.KryoRegisterSerialize
0.007207:com.my.tools.serialize.FSTSerialize
0.00811:com.my.tools.serialize.KryoSerialize
0.010137:com.my.tools.serialize.GsonSerialize
0.012367:com.my.tools.serialize.FastjsonSerialize
0.021474:com.my.tools.serialize.JDKSerialize
1.JDKSerialize
方法一:若Student类仅仅实现了Serializable接口;
方法二:若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out);
方法三:若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,
public static byte[] serialize(Object obj) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
byte[] bs = baos.toByteArray();
baos.close();
oos.close();
return bs;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object deserialize(byte[] bits) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bits);
ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = ois.readObject();
bais.close();
ois.close();
return obj;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
2.FastjsonSerialize
一个JSON库涉及的最基本功能就是序列化和反序列化。Fastjson支持java bean的直接序列化。 使用com.alibaba.fastjson.JSON这个类进行序列化和反序列化。
public static String serialize(Object obj){
String json = JSON.toJSONString(obj);
return json;
}
public static Object deserialize(String json, Class> clazz){
Object obj = JSON.parseObject(json, clazz);
return obj;
}
3.FSTSerialize
FST fast-serialization 是重新实现的 Java 快速对象序列化的开发包。序列化速度更快(2-10倍)、体积更小,而且兼容 JDK 原生的序列化。
要求 JDK 1.7 支持。
Java 快速序列化库 FST 已经发布了 2.0 版本,该版本的包名已经更改,无法平滑升级。另外官方建议为了稳定性考虑还是使用最新的 1.58 版本为好
static FSTConfiguration configuration = FSTConfiguration
.createDefaultConfiguration();
public static byte[] serialize(Object obj){
return configuration.asByteArray((Serializable)obj);
}
public static Object deserialize(byte[] sec){
return configuration.asObject(sec);
}
4.GsonSerialize
这里采用JSON格式同时使用采用Google的gson-2.2.4.jar 进行转义.
static Gson gson = new Gson();
public static String serialize(Object obj){
String json = gson.toJson(obj);
return json;
}
public static Object deserialize(String json, Class> clazz){
Object obj = gson.fromJson(json, clazz);
return obj;
}
5.JacksonSerialize
Jackson库(http://jackson.codehaus.org),是基于java语言的开源json格式解析工具,整个库(使用最新的2.2版本)包含3个jar包:
jackson-core.jar——核心包(必须),提供基于“流模式”解析的API。
jackson-databind——数据绑定包(可选),提供基于“对象绑定”和“树模型”相关API。
jackson-annotations——注解包(可选),提供注解功能。
Jackson的优势:
相对于java json解析的其他库,诸如json-lib、gson包,Jackson具有以下优点:
功能全面,提供多种模式的json解析方式,“对象绑定”使用方便,利用注解包能为我们开发提供很多便利。
性能较高,“流模式”的解析效率超过绝大多数类似的json包。
核心包:JsonPaser(json流读取),JsonGenerator(json流输出)。
数据绑定包:ObjectMapper(构建树模式和对象绑定模式),JsonNode(树节点)
public static String serialize(Object obj){
ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
json = mapper.writeValueAsString(obj);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return json;
}
public static Object deserialize(String json, Class> clazz){
ObjectMapper mapper = new ObjectMapper();
Object obj = null;
try {
obj = mapper.readValue(json, clazz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
6.KryoSerialize 和 KryoRegisterSerialize
Kryo的运行速度是java Serializable 的20倍左右
Kryo的文件大小是java Serializable的一半左右
Kryo有两种模式:
一种是先注册(regist),再写对象,即writeObject函数,实际上如果不先注册,在写对象时也会注册,并为class分配一个id。
注意,如果是rpc,则必须两端都按同样的顺序注册,否则会出错,因为必须要明确类对应的唯一id。
另一种是写类名及对象,即writeClassAndObject函数。
writeClassAndObject函数是先写入(-1 + 2)(一个约定的数字),再写入类ID(第一次要先写-1,再写类ID + 类名),写入引用关系(见引用的实现),最后才写真正的数据)。
注意每一次writeClassAndObject调用后信息都会清空,所以不用担心和client交互时会出错。
static Kryo kryo = new Kryo();
public static byte[] serialize(Object obj) {
byte[] buffer = new byte[2048];
Output output = new Output(buffer);
kryo.writeClassAndObject(output, obj);
byte[] bs = output.toBytes();
output.close();
return bs;
}
public static Object deserialize(byte[] src) {
Input input = new Input(src);
Object obj = kryo.readClassAndObject(input);
input.close();
return obj;
}
static Kryo kryo = null;
static{
kryo = new Kryo();
kryo.setReferences(false);
kryo.setRegistrationRequired(false);
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
}
public static byte[] serialize(Object obj) {
kryo.register(obj.getClass());
byte[] buffer = new byte[2048];
Output output = new Output(buffer);
kryo.writeObject(output, obj);
byte[] bs = output.toBytes();
output.close();
return bs;
}
public static Object deserialize(byte[] src, Class> clazz) {
kryo.register(clazz);
Input input = new Input(src);
Object obj = kryo.readObject(input, clazz);
input.close();
return obj;
}
Json的优点:明文结构一目了然,可以跨语言,属性的增加减少对解析端影响较小。缺点:字节数过多,依赖于不同的第三方类库。
Object Serializalbe 优点:java原生支持,不需要提供第三方的类库,使用比较简单。缺点:无法跨语言,字节数占用比较大,某些情况下对于对象属性的变化比较敏感。
对象在进行序列化和反序列化的时候,必须实现Serializable接口,但并不强制声明唯一的serialVersionUID,是否声明serialVersionUID对于对象序列化的向上向下的兼容性有很大的影响。
我们通常以为将Java对象序列化成二进制比序列化成XML或Json更快,其实是错误的,如果你关心性能,建议避免Java序列化。