Kroy 是一个相对来讲性能和序列化之后的大小,都是比较好的一个序列化框架,项目git地址:java
https://github.com/EsotericSoftware/kryogit
Log.set(1); // 这里是开启kroy 的 trace的日志功能,能够看到具体的序列化和反序列化过程。 Kryo kryo = new Kryo(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Output output = new Output(outputStream); User user = new User(); user.setName("test"); user.setId(12); user.setPassword("test"); List list = new ArrayList(); list.add("test"); list.add("test"); list.add("p"); user.setOrders(list); kryo.writeObject(output, user); // kryo.writeClassAndObject(output, user); output.close(); byte[] bytes = outputStream.toByteArray(); // System.out.println("string == " + bytesToHexString(bytes)); System.out.println("=============== " + bytes.length); System.out.println(new String(bytes)); System.out.println(binary(bytes , 16)); ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); Input input = new Input(inputStream); User copy = kryo.readObject(input , User.class); // User copy = (User) kryo.readClassAndObject(input); input.close(); System.out.println(user); System.out.println(copy);
kroy是根据对应的序列化实体的全部的字段 , 进行序列化操做,不会调用你设置的 实体的 set字段的方法。 eg : 序列化的反序列化不会调用这里的setName方法。
class User { String name ; public setName(){ this.name = name + "_update"; } }
若是你包含非空的构造方法,则,必须强制添加一个空的空的构造方法,能够是私有的构造方法。
在 kroy中,提供了register功能,register究竟是作什么用的 ?若是开启了kroy的日志功能,咱们能够看到以下的输出:
:00 DEBUG: [kryo] Class not available: java.time.ZoneOffset 00:00 DEBUG: [kryo] Class not available: java.time.ZoneId 00:00 DEBUG: [kryo] Class not available: java.time.OffsetTime 00:00 DEBUG: [kryo] Class not available: java.time.OffsetDateTime 00:00 DEBUG: [kryo] Class not available: java.time.ZonedDateTime 00:00 DEBUG: [kryo] Class not available: java.time.Year 00:00 DEBUG: [kryo] Class not available: java.time.YearMonth 00:00 DEBUG: [kryo] Class not available: java.time.MonthDay 00:00 DEBUG: [kryo] Class not available: java.time.Period 00:00 TRACE: [kryo] Register class ID 0: int (com.esotericsoftware.kryo.serializers.DefaultSerializers$IntSerializer) 00:00 TRACE: [kryo] Register class ID 1: String (com.esotericsoftware.kryo.serializers.DefaultSerializers$StringSerializer) 00:00 TRACE: [kryo] Register class ID 2: float (com.esotericsoftware.kryo.serializers.DefaultSerializers$FloatSerializer) 00:00 TRACE: [kryo] Register class ID 3: boolean (com.esotericsoftware.kryo.serializers.DefaultSerializers$BooleanSerializer) 00:00 TRACE: [kryo] Register class ID 4: byte (com.esotericsoftware.kryo.serializers.DefaultSerializers$ByteSerializer) 00:00 TRACE: [kryo] Register class ID 5: char (com.esotericsoftware.kryo.serializers.DefaultSerializers$CharSerializer) 00:00 TRACE: [kryo] Register class ID 6: short (com.esotericsoftware.kryo.serializers.DefaultSerializers$ShortSerializer) 00:00 TRACE: [kryo] Register class ID 7: long (com.esotericsoftware.kryo.serializers.DefaultSerializers$LongSerializer) 00:00 TRACE: [kryo] Register class ID 8: double (com.esotericsoftware.kryo.serializers.DefaultSerializers$DoubleSerializer) 00:00 TRACE: [kryo] Register class ID 9: void (com.esotericsoftware.kryo.serializers.DefaultSerializers$VoidSerializer)
能够看到, 他把java内置的一些类型,注册了一个 ID, 这个ID标识具体的 字段采用什么方法序列化,能够减小序列化之后的大小。github
具体能够看下面的过程:数组
00:00 TRACE: [kryo] Optimize ints: true 00:00 TRACE: [kryo] Field id: int 00:00 TRACE: [kryo] Field name: class java.lang.String 00:00 TRACE: [kryo] Field password: class java.lang.String 00:00 TRACE: [kryo] Field orders: interface java.util.List 00:00 TRACE: [kryo] Register class name: User (com.esotericsoftware.kryo.serializers.FieldSerializer) 00:00 TRACE: [kryo] FieldSerializer.write fields of class: User 00:00 TRACE: [kryo] Write field: name (User) pos=2 00:00 TRACE: [kryo] Write initial object reference 1: test 00:00 TRACE: [kryo] Write: test 00:00 TRACE: [kryo] Write field: orders (User) pos=7 00:00 TRACE: [kryo] Register class name: java.util.ArrayList (com.esotericsoftware.kryo.serializers.CollectionSerializer) 00:00 TRACE: [kryo] Write class name: java.util.ArrayList 00:00 TRACE: [kryo] Write initial object reference 2: [test, test, p] 00:00 DEBUG: [kryo] Write: [test, test, p] 00:00 TRACE: [kryo] Write class 1: String 00:00 DEBUG: [kryo] Write object reference 1: test 00:00 TRACE: [kryo] Write class 1: String 00:00 DEBUG: [kryo] Write object reference 1: test 00:00 TRACE: [kryo] Write class 1: String 00:00 TRACE: [kryo] Write initial object reference 3: p 00:00 TRACE: [kryo] Write: p 00:00 TRACE: [kryo] Write field: password (User) pos=38 00:00 DEBUG: [kryo] Write object reference 1: test 00:00 TRACE: [kryo] Object graph complete.
对于咱们一些自定义的字段,咱们也能够调用 kroy 的方法,主动注册:安全
com.esotericsoftware.kryo.Kryo#register(java.lang.Class, int)
主动编码一个ID出来。多线程
** 说明:**并发
writeObject 和 readObject 属于一对关系,采用 writeObject 序列化, 则必须 采用 readObject 反序列化。框架
writeClassAndObject 和 readClassAndObject 如此。性能
** 两个的区别: **ui
public <T> T readObject (Input input, Class<T> type) public Object readClassAndObject (Input input)
因为readClassAndObject 在反序列化的时候,不须要知道具体的实体的类型 , 因此 writeClassAndObject 序列化的时候,将对于的类的类的名字,添加到了序列化的流的头部。因此, writeClassAndObject之后的字符流要比readObject大一些。
咱们将序列化之后的byte[]打印出来以下: 因为是采用字符串打印,因此,有乱码正常。 writeClassAndObject 结果:
bytes.length 54 字符串 : com.test.Use�tes�java.util.ArrayLis��p
writeObject 结果:
bytes.length 39 字符串 : tes� java.util.ArrayLis��p
bytes数组的大小,一个是 54 , 一个是 39 , 差异仍是比较大。
能够理解为引用,我举一个例子能够说明:
有一个以下的实例:
class User { String name , String password , …… }
咱们在实例化的时候以下: new User("name" , "name") , name 和 password 赋值相同,则,kroy在序列化的时候,第二个字段会采用相似指针的形式,指向对一个 name的值。 能够减小序列化之后的字符流的大小。
kroy实例不是线程安全的,若是是多线程访问,建议采用线程池的形式:
KryoFactory factory = new KryoFactory() { public Kryo create () { Kryo kryo = new Kryo(); // configure kryo instance, customize settings return kryo; } }; // Build pool with SoftReferences enabled (optional) KryoPool pool = new KryoPool.Builder(factory).softReferences().build(); Kryo kryo = pool.borrow(); // do s.th. with kryo here, and afterwards release it pool.release(kryo);
了解这些,能够大概对kroy有个整体的认识和理解 。 更深刻的认识仍是建议参考官方文档。