Skip to content

[Kryo5][scala] Case class serialization issue: TestVarArgs(vargs: String*) #954

Description

@roczei

Describe the bug

Kryo5 cannot serialize the following scala case class which has one variable length argument:

case class TestVarArgs(vargs: String*)

It works with Kryo4 (4.0.2). Seems like this is a regression issue in Kryo5.

Error message:

[warn] either append it to `Global / excludeLintKeys` or call .withRank(KeyRanks.Invisible) on the key
[info] running com.roczei.testing.Main 
[error] com.esotericsoftware.kryo.kryo5.KryoException: java.lang.ClassCastException: class [Ljava.lang.String; cannot be cast to class java.lang.String ([Ljava.lang.String; and java.lang.String are in module java.base of loader 'bootstrap'
[error] Serialization trace:
[error] array (scala.collection.mutable.WrappedArray$ofRef)
[error] vargs (com.roczei.testing.TestVarArgs)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.ReflectField.write(ReflectField.java:101)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.FieldSerializer.write(FieldSerializer.java:108)
[error] 	at com.esotericsoftware.kryo.kryo5.Kryo.writeObject(Kryo.java:642)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.ReflectField.write(ReflectField.java:70)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.FieldSerializer.write(FieldSerializer.java:108)
[error] 	at com.esotericsoftware.kryo.kryo5.Kryo.writeObject(Kryo.java:627)
[error] 	at com.roczei.testing.Main$.main(Main.scala:21)
[error] 	at com.roczei.testing.Main.main(Main.scala)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] Caused by: java.lang.ClassCastException: class [Ljava.lang.String; cannot be cast to class java.lang.String ([Ljava.lang.String; and java.lang.String are in module java.base of loader 'bootstrap')
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.DefaultSerializers$StringSerializer.write(DefaultSerializers.java:164)
[error] 	at com.esotericsoftware.kryo.kryo5.Kryo.writeObjectOrNull(Kryo.java:692)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.ReflectField.write(ReflectField.java:79)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.FieldSerializer.write(FieldSerializer.java:108)
[error] 	at com.esotericsoftware.kryo.kryo5.Kryo.writeObject(Kryo.java:642)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.ReflectField.write(ReflectField.java:70)
[error] 	at com.esotericsoftware.kryo.kryo5.serializers.FieldSerializer.write(FieldSerializer.java:108)
[error] 	at com.esotericsoftware.kryo.kryo5.Kryo.writeObject(Kryo.java:627)
[error] 	at com.roczei.testing.Main$.main(Main.scala:21)
[error] 	at com.roczei.testing.Main.main(Main.scala)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] stack trace is suppressed; run last Compile / run for the full output
[error] (Compile / run) com.esotericsoftware.kryo.kryo5.KryoException: java.lang.ClassCastException: class [Ljava.lang.String; cannot be cast to class java.lang.String ([Ljava.lang.String; and java.lang.String are in module java.base of loader 'bootstrap')
[error] Serialization trace:
[error] array (scala.collection.mutable.WrappedArray$ofRef)
[error] vargs (com.roczei.testing.TestVarArgs)
[error] Total time: 1 s, completed 18 Apr 2023, 19:23:51

Other test results:

https://github.com/roczei/kryo_repro/blob/main/repro-logs-kryo5-bad.txt

To Reproduce

Example scala code:

import com.esotericsoftware.kryo.kryo5.Kryo
import com.esotericsoftware.kryo.kryo5.io.Input
import com.esotericsoftware.kryo.kryo5.io.Output
import com.esotericsoftware.kryo.kryo5.objenesis.strategy.StdInstantiatorStrategy

import java.io.{FileInputStream, FileOutputStream}

case class TestVarArgs(vargs: String*)

object Main {
  def main(args: Array[String]): Unit = {
    val kryo = new Kryo()
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy())
    kryo.register(classOf[TestVarArgs])
    kryo.register(Class.forName("scala.collection.immutable.ArraySeq$ofRef"))
    kryo.register(Class.forName("[Ljava.lang.String;"))
    val t = TestVarArgs("hey", "you", "guys")
    val output = new Output(new FileOutputStream("file.bin"))
    kryo.writeObject(output, t)
    output.close()
    val input = new Input(new FileInputStream("file.bin"))
    val i = kryo.readObject(input, classOf[TestVarArgs])
    input.close()
    assert(i.equals(t))
  }
}

Bad results (Kryo5):

git clone git@github.com:roczei/kryo_repro.git
cd scala_project_kryo5-2.13.8
sbt run

or

cd scala_project_kryo5-2.12.7
sbt run

or

cd scala_project_kryo5-2.11.12
sbt run

Console outputs: https://github.com/roczei/kryo_repro/blob/main/repro-logs-kryo5-bad.txt

Good result (Kryo4)

cd scala_project_kryo4-2.13.8
sbt run

Console output:

https://github.com/roczei/kryo_repro/blob/main/kryo4-good-logs.txt

OS: macosx but I think this is not OS related
JDK: Azul Systems, Inc. Java 11.0.16 / Azul Systems, Inc. Java 1.8.0_345 (probably it can be reproduced with other jave versions as well)
Scala versions: 2.11.12, 2.12.7, 2.13.8
Kryo Version: all Kryo5 versions

Additional context

I would like to finish this pull request what nicknezis has started (update chill to the newer Kryo 5): twitter/chill#514 and currently this is blocking me to finish this task (latest pull request): roczei/chill#1. Similar issue was mentioned in this kryo thread as well:

https://groups.google.com/g/kryo-users/c/6iBVAKG5p4g

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions