Does Cryo's serialization depend on the version of Java?

When deserializing a serialized object (from a file) using Kryo, I get the following exception:

java.lang.ExceptionInInitializerError (...) Caused by: com.esotericsoftware.kryo.KryoException: (...) Serialization trace: (...) at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:125) at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528) at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:786) at com.esotericsoftware.kryo.serializers.MapSerializer.read(MapSerializer.java:143) at com.esotericsoftware.kryo.serializers.MapSerializer.read(MapSerializer.java:21) at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:682) (...) Caused by: java.lang.IndexOutOfBoundsException: Index: 1582, Size: 2 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) at com.esotericsoftware.kryo.util.MapReferenceResolver.getReadObject(MapReferenceResolver.java:42) at com.esotericsoftware.kryo.Kryo.readReferenceOrNull(Kryo.java:830) at com.esotericsoftware.kryo.Kryo.readObjectOrNull(Kryo.java:753) at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:113) ... 27 more 

My hypothesis is that a serialized format is misunderstood when deserializing (i.e. changing). The version of Kryo for serialization and deserialization was the same. The Java version could be different during serialization: could this be an explanation?

If not, any other hints that mine throw such exceptions are more than welcome!

Thanks a lot, Thomas

UPDATE: as suggested, thereby a class that is deserialized from a file

The main deserialized class is HashMap<Integer, PreflopEhsVO> where user-defined class definitions (child and parent):

 public class PreflopEhsVOExtended extends PreflopEhsVO{ private int numbValues = 0; public synchronized void addValue(PreflopEhsVO values){ if (numbValues == 0) this.valuesPerNumbOpp = values.valuesPerNumbOpp; else{ //Weighted avg for (int i=0; i<this.valuesPerNumbOpp.length; ++i) this.valuesPerNumbOpp[i] = (this.valuesPerNumbOpp[i] * numbValues + values.valuesPerNumbOpp[i]) / (float) (numbValues + 1); ++numbValues; } } public PreflopEhsVOExtended(PreflopEhsVO values) { this.valuesPerNumbOpp = values.valuesPerNumbOpp; this.numbValues = 1; } } public class PreflopEhsVO { public float[] valuesPerNumbOpp = new float[9]; public PreflopEhsVO(){ } public PreflopEhsVO(float[] valuesPerNumbOpp) { this.valuesPerNumbOpp = valuesPerNumbOpp; } } 
+6
source share
1 answer

Kryo is usually unstable for different JVMs unless you are very careful about how you register types.

When Kryo encounters a type that he did not see before he increments the counter and registers the type for that value. It uses these values ​​in the object graph as an alias for the type (optimization for performance). If the execution order is slightly different from the second JVM (regardless of whether the version is the same), then Kryo will have different type registers with an alias. This prevents the deserialization of serialized drops.

The solution to this is to enable strict mode in kryo and manually register classes with explicit identifiers.

  kryo.register(SomeClass.class, 1); kryo.register(AnotherClass.class, 2); 

This ensures that classes are registered with the same stable identifiers on both JVMs. If you do, you can get stable cross-serialization of the JVM.

Another possible problem might be changing the fields of the pre and post serialization class. The only practical way to handle changing fields is with a TaggedFieldSerializer

+5
source

All Articles