com.esotericsoftware.kryo.KryoException: Encountered unregistered class ID: XXXX
当Kryo写出一个对象的实例时,首先可能需要写出一些标识对象类的东西。默认情况下,写入完整类名,然后写入该对象的字节。后续出现的同一类对象图的对象用变长的int来写(using a variable length int)。
写类的名字有点低效,所以类可以事先注册:kryo.register(SomeClass.class);这样的话,SomeClass 注册到了 Kryo,它将该类与一个 int 型的 ID 相关联。当 Kryo 写出 SomeClass 的一个实例时,它会写出这个 int ID。这比写出类名更有效。在反序列化期间,注册的类必须具有序列化期间相同的 ID 。还有一种情况是kryo每次写入类的完整信息,而不是通过int类型的ID号去代替。
两种情况如何取舍呢?写id的情况,效率会高一些,但是缺陷很明显:所有系列化涉及到的类都需要代码里手工kryo.register(),否则报告unregistered class ID;另外,kryo不能保证”每次jvm重启之后,或者在多台jvm机器之间,同一个类注册到kryo的class ID会相同”,所以这就导致该模式应用于集群会存在严重问题,所以用id代替类信息的模式不建议使用,而且,默认该功能也是关闭的,除非你在代码中显性的调用了以下代码:
1 | kryo.register(SomeClass.class); |
所以遇到Encountered unregistered class ID之类的问题,首先要检查该功能是否被不经意的开启了。如果确保未开启该功能,再考虑以下情况:就是对象太大,导致系列化结果不完整,因为output对象默认的缓存字节数并不大,实际对象超出大小的时候,系列化的时候并不会报告错误,但是系列化结果已经不完整,从而导致反系列化的时候会失败,报告的错误一般也是Encountered unregistered class ID。
com.esotericsoftware.kryo.KryoException: Buffer underflow.
- 检查反序列化数据与反序列化类是否一致,如果当前数据与反序列化类不一致,有可能抛出该异常。
can’t serializer AtomicDouble
默认情况下序列化AtomicDouble,再反序列化回来,AtomicDouble里面的数值为0.0,即数据丢失了。
1 | /** |