Kryo目前更新到5.0版本: GitHub - EsotericSoftware/kryo: Java binary serialization and cloning: fast, efficient, automatic
4.0版本和5.0版本的文档差距比较大,5.0要讲解的详细很多,建议还是看5.0
1.Round trip
这段代码的意思是没有经过流进行传输序列化后的对象,而是将序列化后的字节直接存储在buffer字节数组中,也就是序列化到字节并返回到对象
Kryo kryo = new Kryo();
// Register all classes to be serialized.
kryo.register(SomeClass.class);
SomeClass object1 = new SomeClass();
Output output = new Output(1024, -1);
kryo.writeObject(output, object1);
Input input = new Input(output.getBuffer(), 0, output.position());
SomeClass object2 = kryo.readObject(input, SomeClass.class);
// output.getBuffer()直接在buffer数组里取出字节序列
源码:
public Output(int bufferSize, int maxBufferSize) {
this.varEncoding = true;
if (bufferSize > maxBufferSize && maxBufferSize != -1) {
throw new IllegalArgumentException("bufferSize: " + bufferSize + " cannot be greater than maxBufferSize: " + maxBufferSize);
} else if (maxBufferSize < -1) {
throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize);
} else {
this.capacity = bufferSize;
this.maxCapacity = maxBufferSize == -1 ? 2147483639 : maxBufferSize;
this.buffer = new byte[bufferSize]; // 存储在buffer不经过流
}
}
用来代替上面的Round trip
即:Kryo 支持使用从一个对象到另一个对象的直接赋值来制作对象的深拷贝和浅拷贝。这比序列化为字节并返回对象更有效
Kryo kryo = new Kryo();
SomeClass object = ...
SomeClass copy1 = kryo.copy(object);
SomeClass copy2 = kryo.copyShallow(object);
3.Kryo的Register:
Kryo大体有三种序列化方法,每种方式都有其优势和劣势。
1. 也是最为简单的一种,就是writeObject/readObject ,这种方法只会序列化对象实例,而不会记录对象所属类的任何信息。优势是最节省空间,劣势是在反序列化时,需要提供类作为模板才能顺利反序列。如上述,我们在反序列化时,就提供了Dog.class进行反序列化。
2. 就是使用 writeClassAndObject ,这种方法会先将对象所属类的全限定名序列化,然后再依次序列化对象实例的成员。优势是完全动态序列化,整个Kryo周期都不需要提供类信息。反序列化时使用 readClassAndObject 。这算是kryo的一个特点,可以把对象信息直接写到序列化数据里,反序列化的时候可以精确地找到原始类信息,不会出错,这意味着在写readClassAndObject 方法时,无需传入Class或Type类信息。
3. 也是使用 writeClassAndObject ,但是我们在这之前会先进行注册,事先将需要序列化的类注册给 Kryo(此时类和唯一id绑定),之后使用 writeClassAndObject 序列化时,只会序列化注册id,而不会序列化类的全限定名了,这样大大节省了空间(通常只比writeObject多一个字节)。反序列化时使用readClassAndObject 。但是特别需要注意序列化和反序列的Kryo的注册信息应当保持一致。
注意:
1>使用 writeClassAndObject 时,如果序列化 和反序列化不是用的同一个 kryo实例,这里的 ID必须都要调用register方法注册相同的ID。例如RPC调用中, 否则会出现反序列化出错的情况
2>使用writeObject/readObject 不需要注册 因为提供了模板 更节省空间
这时候禁用注册即可
kryo.setRegistrationRequired(false); //默认就是禁止的 True标识开启注册
4.补充的一些知识
Kryo 序列化说明 - 爱无痕的个人空间 - OSCHINA - 中文开源技术交流社区
5.比较详细的Kryo入门