Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kryo does not correctly support parameterized type hierarchy #377

Closed
mathieucarbou opened this issue Dec 17, 2015 · 4 comments
Closed

Kryo does not correctly support parameterized type hierarchy #377

mathieucarbou opened this issue Dec 17, 2015 · 4 comments

Comments

@mathieucarbou
Copy link

Test case:

@RunWith(JUnit4.class)
public class SerializationTest {

  @Test
  public void testParameterizedTypesSupport() throws Exception {
    LongHolder o1 = new LongHolder(1L);
    LongListHolder o2 = new LongListHolder(asList(1L));

    Kryo kryo = new Kryo();
    Output buffer = new Output(512, 4048);
    kryo.writeClassAndObject(buffer, o1);
    kryo.writeClassAndObject(buffer, o2);
  }

  interface Holder<V> {
    V getValue();
  }

  static abstract class AbstractValueHolder<V> implements Holder<V> {
    private final V value;

    AbstractValueHolder(V value) {
      this.value = value;
    }

    @Override
    public V getValue() {
      return value;
    }
  }

  static abstract class AbstractValueListHolder<V> extends AbstractValueHolder<List<V>> {
    AbstractValueListHolder(List<V> value) {
      super(value);
    }
  }

  static class LongHolder extends AbstractValueHolder<Long> {
    LongHolder(Long value) {
      super(value);
    }
  }

  static class LongListHolder extends AbstractValueListHolder<Long> {
    LongListHolder(List<Long> value) {
      super(value);
    }
  }
}

Error:

com.esotericsoftware.kryo.KryoException: java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.lang.Long
Serialization trace:
value (org.terracotta.management.SerializationTest$LongListHolder)

    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:101)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:518)
    at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:628)
    at org.terracotta.management.SerializationTest.testParameterizedTypesSupport(SerializationTest.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.lang.Long
    at com.esotericsoftware.kryo.serializers.DefaultSerializers$LongSerializer.write(DefaultSerializers.java:141)
    at com.esotericsoftware.kryo.Kryo.writeObjectOrNull(Kryo.java:606)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:87)
    ... 29 more

Cause:

Kryo reuses the same CachedField instance it previously encountered, but the type changed.

@mathieucarbou
Copy link
Author

FYI @rkavanap

@rgilles
Copy link

rgilles commented Jan 4, 2016

Hi,
I get exactly the same result if I change the test method as follow:

    @Test
    public void testParameterizedTypesSupport() throws Exception {
//        LongHolder o1 = new LongHolder(1L);
        LongListHolder o2 = new LongListHolder(asList(1L));

        Kryo kryo = new Kryo();
        Output buffer = new Output(512, 4048);
//        kryo.writeClassAndObject(buffer, o1);
        kryo.writeClassAndObject(buffer, o2);
    }

======
com.esotericsoftware.kryo.KryoException: java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.lang.Long

As you can see the error comes from the generic usage. If I remove the first serialization it fails.

Best regards.

@jlmorton
Copy link

I believe this is a regression from the following commit: 4764dee

Reverting this commit causes this test to pass.

The superclass for LongListHolder is AbstractValueListHolder, which is parameterized with Long. This is the type that is found in FieldSerializerGenericsUtil#buildGenericsScope at line 79.

I'm not sure what the fix for this is, but at this point generic scope is set to Long, and Kryo ultimately gets a LongSerializer when it needs to serialize a list.

@magro
Copy link
Collaborator

magro commented Jul 1, 2016

Resolved by #433

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

No branches or pull requests

4 participants