/**** FIX FOR HIBERNATE OBJECT */
if (PersistenceUtils.isProxy(value)){
if(!Hibernate.isInitialized(value)){
if (INFO)
info("kryo", "uninitialized hibernate proxy detected and initializing: " + this + " (" + object.getClass().getName() + ")" + " pos=" + output.position());
Hibernate.initialize(value);
}
value = PersistenceUtils.cleanFromProxies(value);
if (INFO)
info("kryo", "Write field detected hibernate proxy and unproxying: " + this + " (" + object.getClass().getName() + ")" + " pos=" + output.position());
}
/****END OF FIX *****/
kryoSerializer = new Kryo() {
@Override
public Serializer<?> getDefaultSerializer( final Class type ) {
if (AbstractPersistentCollection.class.isAssignableFrom( type )) {
return new FieldSerializer( kryoSerializer, type );
}
return super.getDefaultSerializer( type );
}
}
write
method of the serializer and unwrap the proxy before calling super.write
my take on this is:
public class KryoSerializer {
private static final KryoFactory factory = () -> {
Kryo kryo = new Kryo();
return kryo;
};
private static final KryoPool pool = new KryoPool.Builder(factory)
.softReferences()
.build();
public byte[] serialize(Object object) {
Output output = new Output(new ByteArrayOutputStream());
Kryo kryo = pool.borrow();
kryo.writeClassAndObject(output, object);
output.close();
pool.release(kryo);
return output.getBuffer();
}
public Object deserialize(byte[] byteArray) {
Input input = new Input(byteArray);
Kryo kryo = pool.borrow();
Object object = kryo.readClassAndObject(input);
input.close();
pool.release(kryo);
return object;
}
}
Do you see any problem with this implementation?
KryoPool
class is not included anymore. Couldn't find anything in migration guide either: https://github.com/EsotericSoftware/kryo/wiki/Migration-to-v5Hi, not sure if I should create a Github issue for it, but here's my problem:
Kryo 5.0.0 fails to instantiate on Android 11 with this exception:
java.lang.NoSuchMethodError: No static method of()Ljava/util/Map; in class Ljava/util/Map$-DC; or its super classes
at com.esotericsoftware.kryo.serializers.ImmutableCollectionsSerializers$JdkImmutableMapSerializer.addDefaultSerializers(ImmutableCollectionsSerializers.java:118)
at com.esotericsoftware.kryo.serializers.ImmutableCollectionsSerializers.addDefaultSerializers(ImmutableCollectionsSerializers.java:39)
at com.esotericsoftware.kryo.Kryo.<init>(Kryo.java:231)
...
For some reason, there was no problem for it to add default serializers for List.of().
Not sure what is going on here, somehow it found "java.util.ImmutableCollections" class but failed to call java.util.Map.of(). The device is Pixel 4 with official firmware so I'd expect such behavior on many other devices.
Is there any way to force Kryo not to load default serializers for immutable collections? Maybe some gradle magic which allows to replace a class or something. I could think of a couple of ways to solve this but all of them would require to change Kryo's source code:
Map.of(), List.of(), Set.of() / copyOf() can't be resolved in my ide running on sourceCompatability of Java 8 - I thought it might be the case but still not sure upgrading to Java 9+ makes sense for Android (also would require a bit of .gradle refactoring which I'm not a fan of) so had no chance checking it
If anyone can explain anything of these to me I'll be very grateful!
Also thanks for making Kryo, it is cool
java.util.ImmutableCollections
is on the classpath:if (isClassAvailable("java.util.ImmutableCollections")) {
JdkImmutableListSerializer.addDefaultSerializers(kryo);
JdkImmutableMapSerializer.addDefaultSerializers(kryo);
JdkImmutableSetSerializer.addDefaultSerializers(kryo);
}
ImmutableCollectionsSerializers.addDefaultSerializers()
and check why isClassAvailable
returns true
?
Map.of
overloads should be available
Hello ,
I have a problem of deserailisation with a complex class case (see log),
Ps => despite the warning, I noticed nothing as a malfunction,
I use in my project:
akka 2.6.11 ( akka cluster , akka streams , akka pubsub )
scala 2.12,
play 2.6
log server:
[warn] 2020-11-30 19:09:31,504 - akka.remote.artery.Deserializer - Failed to deserialize message from [akka://application@127.0.0.1:2551] with serializer id [123454323] and manifest []. com.esotericsoftware.kryo.KryoException: java.lang.NullPointerException
Serialization trace:
underlying (play.api.libs.json.JsObject)
data (models.TaskModel)
task (actors.websockets.ClientActor$TaskDeleted)
[info] 2020-11-30 19:09:31,504 - actors.websockets.ClientActor - task deleted, id: 66657
[warn] 2020-11-30 19:09:31,504 - akka.remote.artery.Deserializer - Failed to deserialize message from [akka://application@127.0.0.1:2551] with serializer id [123454323] and manifest []. com.esotericsoftware.kryo.KryoException: java.lang.NullPointerException
Hello, I am using Kryo 4.0.2 together with "de.javacaffee" % "kryo-serializers" % "0.45" as well as "io.altoo" % "akka-kryo-serialization" % "1.1.0" to do serialization between Akka nodes. Recently we had a case class that had a play.api.libs.json.JsValue as type. JsValue is a trait with various concrete classes for the various parts of a JSON tree (JSString, JSObject, etc...). I noticed that when trying to transfer the case class between nodes, a NullpointerException was raised and the connection between the nodes got disrupted. I only got it to work by explicitly declaring a custom serializer for each concrete implementation of JsValue as indicated below :
abstract class PlayJsonSerializer[T <: JsValue] extends Serializer[T] {
override def write(kryo: Kryo, output: Output, `object`: T): Unit = output.writeString(Json.stringify(`object`))
override def read(kryo: Kryo, input: Input, `type`: Class[T]): T = Json.parse(input.readString()).asInstanceOf[T]
}
class JsValueSerializer extends PlayJsonSerializer[JsValue]
class JsObjectSerializer extends PlayJsonSerializer[JsObject]
class JsStringSerializer extends PlayJsonSerializer[JsString]
class JsNumberSerializer extends PlayJsonSerializer[JsNumber]
class JsBooleanSerializer extends PlayJsonSerializer[JsBoolean]
class JsArraySerializer extends PlayJsonSerializer[JsArray]
class JsNullSerializer extends PlayJsonSerializer[JsNull.type]
Is this the only way to serialize a Play Json value with Kryo ? Or am I missing something ?