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

ClassCastException When Writing a Map After Previously Reading a Map with Different Generic Type #384

Closed
jlmorton opened this issue Feb 12, 2016 · 1 comment
Milestone

Comments

@jlmorton
Copy link

While reading an object with a generic type map, Kryo will create a MapSerializer and set the generic type on the serializer. When the FieldSerializer encounters a reference to the same map, it will again set the generic types of the MapSerializer, but will return without re-setting the generic types.

After this, a subsequent request to serialize a map with different generic types different will lead to a ClassCastException, as demonstrated in the test case below:

@Test
public void testSerializeMapAfterDeserialization() throws IOException {
    Kryo kryo = new Kryo();

    byte[] serializedMapHolder = serialize(kryo, new MapHolder());
    deserialize(kryo, serializedMapHolder);

    Map<Integer, List<String>> stringMap = new HashMap<>();
    stringMap.put(1, new ArrayList<>());
    serialize(kryo, stringMap);
}

static class MapHolder {
    private Map<Integer, String> mapOne = new HashMap<>();
    private Map<Integer, String> mapTwo = this.mapOne;
}

private byte[] serialize(Kryo kryo, Object object) throws IOException {
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Output output = new Output(outputStream)) {
        kryo.writeClassAndObject(output, object);
        output.flush();
        return outputStream.toByteArray();
    }
}

private Object deserialize(Kryo kryo, byte[] serializedBytes) throws IOException {
    try (ByteArrayInputStream inputStream = new ByteArrayInputStream(serializedBytes); Input input = new Input(inputStream)) {
        return kryo.readClassAndObject(input);
    }
}

This test case results in the following error:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String

at com.esotericsoftware.kryo.serializers.DefaultSerializers$StringSerializer.write(DefaultSerializers.java:184)
at com.esotericsoftware.kryo.Kryo.writeObjectOrNull(Kryo.java:603)
at com.esotericsoftware.kryo.serializers.MapSerializer.write(MapSerializer.java:109)
at com.esotericsoftware.kryo.serializers.MapSerializer.write(MapSerializer.java:39)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:625)
at com.test.MapSerializerTest.serialize(MapSerializerTest.java:36)
at com.test.MapSerializerTest.testSerializeMapAfterDeserialization(MapSerializerTest.java:26)
jlmorton pushed a commit to jlmorton/kryo that referenced this issue Feb 14, 2016
jlmorton pushed a commit to jlmorton/kryo that referenced this issue Feb 14, 2016
jlmorton pushed a commit to jlmorton/kryo that referenced this issue Feb 14, 2016
@magro magro added this to the 3.1.0 milestone Mar 4, 2016
magro added a commit to magro/kryo that referenced this issue Jun 17, 2016
@magro
Copy link
Collaborator

magro commented Jul 1, 2016

Resolved with #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

2 participants