You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When data was serialized and after that a new field was added, deserilization fails with exception: com.esotericsoftware.kryo.kryo5.io.KryoBufferUnderflowException: Buffer underflow Stacktrace
Exception in thread "main" com.esotericsoftware.kryo.kryo5.io.KryoBufferUnderflowException: Buffer underflow.
Serialization trace:
info (akta.dcs.session.live.hash.Data)
at com.esotericsoftware.kryo.kryo5.io.Input.require(Input.java:221)
at com.esotericsoftware.kryo.kryo5.io.Input.readVarIntFlag(Input.java:482)
at com.esotericsoftware.kryo.kryo5.io.Input.readString(Input.java:777)
at com.esotericsoftware.kryo.kryo5.serializers.DefaultSerializers$StringSerializer.read(DefaultSerializers.java:174)
at com.esotericsoftware.kryo.kryo5.serializers.DefaultSerializers$StringSerializer.read(DefaultSerializers.java:164)
at com.esotericsoftware.kryo.kryo5.Kryo.readObjectOrNull(Kryo.java:826)
at com.esotericsoftware.kryo.kryo5.serializers.RecordSerializer.read(RecordSerializer.java:136)
at com.esotericsoftware.kryo.kryo5.Kryo.readObject(Kryo.java:777)
Code example:
public record Data(
String id
){}
===============================================
var kryoLocal = ThreadLocal.withInitial(() -> {
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
return kryo;
});
var data = new Data("1");
var output = new Output(1024, -1);
kryoLocal.get().writeObject(output, data);
output.flush();
var serializedData = output.toBytes(); // [-126, 49]
output.close();
After serialized, new field was added:
public record Data(
String id,
String info
){}
=================
var input = new Input(new byte[] {-126, 49});
var deserializedData = kryoLocal.get().readObject(input, Data.class);
input.close();
And eventually an exception is thrown: com.esotericsoftware.kryo.kryo5.io.KryoBufferUnderflowException: Buffer underflow.
But if convert Java record to class, everything works properly: Code example:
public class Data {
private String id;
public Data() {
}
public Data(
String id
) {
this.id = id;
}
public String id() {
return id;
}
}
=====================================
var kryoLocal = ThreadLocal.withInitial(() -> {
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
return kryo;
});
var data = new Data("1");
var output = new Output(1024, -1);
kryoLocal.get().writeObject(output, data);
output.flush();
var serializedData = output.toBytes(); // [1, 105, -28, 3, -126, 49]
output.close();
After serialized, new field was added:
public class Data {
private String id;
private String info;
public Data() {
}
public Data(
String id,
String info
) {
this.id = id;
this.info = info;
}
public String id() {
return id;
}
public String info() {
return info;
}
}
==========================================
var input = new Input(new byte[] {1, 105, -28, 3, -126, 49});
var deserializedData = kryoLocal.get().readObject(input, Data.class);
input.close();
As we can see, that serialized record and class have different bytes.
The text was updated successfully, but these errors were encountered:
investr777
changed the title
Deserialization fails with "Buffer underflow" after add a new field (Issue with backward compatibility)
Deserialization fails with "Buffer underflow" after add a new field to record class (Issue with backward compatibility)
Oct 3, 2023
@investr777: Thanks for the detailed report and sorry for the late answer!
The RecordSerializer currently does not have support for backwards/forwards compatibility. It is a limitation in its design that I realized only after it was originally contributed by Oracle.
See this issue for a more detailed discussion of the problem.
I have created a POC that integrates record serialization back into the default FieldSerializer and its subclasses. I ran your test-case against this PR and it passes. it will be part of the next major release, Kryo 6.
I'm afraid that for Kryo 5 there is not much we can do to fix this. If you need support for this right now and can't switch to normal classes for cases where you need compatibility, you could write your own record serializer that uses the same logic as CompatibleFieldSerializer.
@theigl, thank you so much for your reply.
Will Kryo 6 and Kryo 5 have backward compatibility? Will Kryo 6 be able to deserialized data, which were serialized by Kryo 5?
Kryo version 5.5.0
Java 17
When data was serialized and after that a new field was added, deserilization fails with exception:
com.esotericsoftware.kryo.kryo5.io.KryoBufferUnderflowException: Buffer underflow
Stacktrace
Code example:
After serialized, new field was added:
And eventually an exception is thrown:
com.esotericsoftware.kryo.kryo5.io.KryoBufferUnderflowException: Buffer underflow.
But if convert Java record to class, everything works properly:
Code example:
After serialized, new field was added:
As we can see, that serialized record and class have different bytes.
The text was updated successfully, but these errors were encountered: