kryo icon indicating copy to clipboard operation
kryo copied to clipboard

GraalVM compatibility

Open mrniko opened this issue 2 years ago • 13 comments
trafficstars

Is your feature request related to a problem? Please describe. Make Kryo lib GraalVM compatible

Describe the solution you'd like Some of serializers can't be used in GraalVM - https://github.com/redisson/redisson/issues/4811. They needs to be added in reflect-config.json file stored in library.

Describe alternatives you've considered I'm adding it manually in my project now

mrniko avatar Jan 23 '23 09:01 mrniko

@mrniko: My understanding of GraalVM requirements is limited. What serializers would we need to add to the reflect-config.json? All of them?

The issue you linked mentions OffsetDateTimeSerializer, but I don't see how this serializer is different from any other.

theigl avatar Jan 23 '23 10:01 theigl

It's arise if you use OffsetDateTime object. But you use any other object like Duration, Instant... you'll get similar error. I think all Serializers which extends ImmutableSerializer and located in TimeSerializers should be added.

mrniko avatar Jan 23 '23 11:01 mrniko

I attached the sample project. You can use it to reproduce issue with other serializers. Read Readme.md for the build steps. Please note that OffsetDateTimeSerializer already added into \src\main\resources\META-INF\native-image\com.example\micronaut-demo-graalvm\reflect-config.json file.

micronaut-demo-graalvm-master2.zip

mrniko avatar Jan 23 '23 12:01 mrniko

It seems all Serializers extending ImmutableSerializer should be added, not only in TimeSerializers class

mrniko avatar Jan 23 '23 13:01 mrniko

I attached reflect-config.json file with all Serializers

reflect-config.json.zip

mrniko avatar Jan 24 '23 07:01 mrniko

@mrniko: Can you please create a PR with your suggested changes? Then we can discuss this further.

We could add some conditional declarations for serializers: RecordSerializer only makes sense for JDK17+, ImmutableCollectionsSerializers is for JDK11+. I'm not sure this is necessary, but the GraalVM docs recommend it.

theigl avatar Jan 24 '23 10:01 theigl

Here is another issue with GraalVM https://github.com/redisson/redisson/issues/4820

mrniko avatar Feb 08 '23 13:02 mrniko

@mrniko: We have two options here:

  1. Disable unsafe on GraalVM with -Dkryo.unsafe=false.
  2. Change the code in Kryo to use direct assignment to static final fields, so GraalVM can perform the substitutions (see https://developers.redhat.com/articles/2022/05/09/using-unsafe-safely-graalvm-native-image#how_to_fix_unsafe_offset_computations)

I don't use GraalVM in my dayjob, so I can't spend a lot of time on this issue.

If you can provide me with a very simple example project that uses GraalVM + Kryo where I can reproduce these issues, I will attempt to fix them. But it should be a project without Redisson, Quarkus etc. Ideally, just a class that initializes Kryo and does some serialization.

theigl avatar Feb 08 '23 14:02 theigl

Note to myself:

Here is how Netty handles this: https://github.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/internal/PlatformDependent0.java

theigl avatar Feb 08 '23 14:02 theigl

@mrniko thank you for your reflection-config.json, the project we use uses three serializers only so learning the correct format for listing those from your upload, namely allDeclaredConstructors, we're able to use kryo

CGDogan avatar Jul 17 '23 04:07 CGDogan

@CGDogan

You don't need to add reflection-config.json since it's part of Redisson.

mrniko avatar Jul 17 '23 07:07 mrniko

No no, you helped me write as much as we needed to work with kryo and I'm not using Redisson:

{
  "name": "com.esotericsoftware.kryo.serializers.DefaultSerializers$ClassSerializer",
  "allDeclaredConstructors": true
},
{
  "name": "com.esotericsoftware.kryo.serializers.DefaultSerializers$IntSerializer",
  "allDeclaredConstructors": true
},
{
  "name": "com.esotericsoftware.kryo.serializers.DefaultSerializers$StringSerializer",
  "allDeclaredConstructors": true
},

CGDogan avatar Jul 17 '23 07:07 CGDogan

Sorry, Kryo makes classes by loading their bytecode, but this will work iff a generic bytecode is loaded for the class using experimental-class-define-support and then fields are initialized. All loaded bytecode must be known before compiletime hence only "templates" can be loaded. This is how Kryo could work but yes it's a lot of work. For now, it does not I think.

CGDogan avatar Jul 17 '23 09:07 CGDogan