andrewbissada / kryo

Automatically exported from code.google.com/p/kryo
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Caused by: java.lang.ClassCastException: class test.enums.ActivityTypeEnum != null #134

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. When I copy an object:
private static final Kryo kryo = new Kryo();
kryo.copy(object)

What is the expected output? 
The successful copy of the object, like appends on default java serialization.

What do you see instead?
Caused by: java.lang.ClassCastException: class test.enums.ActivityTypeEnum != 
null
    at java.util.EnumMap.typeCheck(EnumMap.java:658)
    at java.util.EnumMap.put(EnumMap.java:241)
    at java.util.EnumMap.put(EnumMap.java:62)
    at com.esotericsoftware.kryo.serializers.MapSerializer.copy(MapSerializer.java:148)
    at com.esotericsoftware.kryo.serializers.MapSerializer.copy(MapSerializer.java:17)
    at com.esotericsoftware.kryo.Kryo.copy(Kryo.java:830)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.copy(FieldSerializer.java:638)
    ... 22 more

What version of the Kryo are you using?
2.21

Please provide any additional information below.
I'm running a test on eclipse IDE.

Original issue reported on code.google.com by agentilr...@gmail.com on 23 Sep 2013 at 10:59

GoogleCodeExporter commented 9 years ago
I resolve this problem using JavaSerializer, provided by kryo.
  JavaSerializer immutableSerializer = new JavaSerializer();
  immutableSerializer.setImmutable(true);

  kryo.register(EnumMap.class, immutableSerializer);

I also do the same on class ArrayList, I have an error when clone an array 
(NullPointerExpception):
  kryo.register(Arrays.asList("dummy").getClass(), immutableSerializer);

As I understand, Kyro for this classes uses default java serialization, with 
less performance, but still funcional. Is that correct?

Thanks

Original comment by agentilr...@gmail.com on 24 Sep 2013 at 11:37

GoogleCodeExporter commented 9 years ago
> As I understand, Kyro for this classes uses default java serialization, with 
less performance, but still 
> funcional. Is that correct?

Yes. This should be the case. 

In theory, Kryo should be able to serialize your classes without this 
JavaSerializer trick, but it does not do it for you. If you want us to 
investigate why, it would be nice if you would provide a self-contained 
test-case.

-Leo

Original comment by romixlev on 24 Sep 2013 at 12:16

GoogleCodeExporter commented 9 years ago
I did some tests and check that I resolved the problem because set 
JavaSerializer as immutable. So, this object is not cloned, and this is not 
what I want.
However, if I set to false, the error still remains.

I reproduce the error in a test class that I attach.
If you can help me I appreciate.

If you run the test, you get the error:
Caused by: java.lang.ClassCastException: class 
pt.ptinovacao.deepcloner.TesteKryoEmptyEnumMap$B != null
    at java.util.EnumMap.typeCheck(EnumMap.java:658)
    at java.util.EnumMap.put(EnumMap.java:241)
    at java.util.EnumMap.put(EnumMap.java:62)
    at com.esotericsoftware.kryo.serializers.MapSerializer.copy(MapSerializer.java:148)
    at com.esotericsoftware.kryo.serializers.MapSerializer.copy(MapSerializer.java:17)
    at com.esotericsoftware.kryo.Kryo.copy(Kryo.java:830)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.copy(FieldSerializer.java:638)
    ... 3 more

Original comment by agentilr...@gmail.com on 24 Sep 2013 at 2:29

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
The attached file

Original comment by agentilr...@gmail.com on 24 Sep 2013 at 2:31

Attachments:

GoogleCodeExporter commented 9 years ago
Just to resume, the error occurs because I create an EnumMap<Enum, C> (where 
class C has a hashmap) with all values initialize with an empty hashmap (class 
C is initialize with empty hashmap).

When kryo tries to clone this EnumMap, is fails (maybe because this value is 
empty).

Original comment by agentilr...@gmail.com on 24 Sep 2013 at 2:45

GoogleCodeExporter commented 9 years ago
Hi,

Is there any reason what is causing the error?
Thanks for the help!

Best regards,
Andre

Original comment by agentilr...@gmail.com on 26 Sep 2013 at 2:31

GoogleCodeExporter commented 9 years ago
Hi,

Kryo does not support EnumMap serialization out of the box. You need a custom 
serializer for it.
The kryo-serializers project provides such a serializer for EnumMap and many 
others:

https://github.com/magro/kryo-serializers/blob/master/src/main/java/de/javakaffe
e/kryoserializers/EnumMapSerializer.java

Simply register this serializer for your class and it should work. Please 
report back if we can close this issue.

-Leo

Original comment by romixlev on 26 Sep 2013 at 2:49

GoogleCodeExporter commented 9 years ago
Hi,

I register the EnumMap custom serializer that you indicates but didn't resolve.
EnumMapSerializer enumSerializer = new EnumMapSerializer();
kryo.register(EnumMap.class, enumSerializer);

Exception in thread "main" com.esotericsoftware.kryo.KryoException: Serializer 
does not support copy: pt.ptinovacao.deepcloner.kryo.EnumMapSerializer
Serialization trace:
atrib (pt.ptinovacao.deepcloner.tests.TesteKryoEmptyEnumMap$A)
    at com.esotericsoftware.kryo.Serializer.copy(Serializer.java:86)
    at com.esotericsoftware.kryo.Kryo.copy(Kryo.java:830)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.copy(FieldSerializer.java:638)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.copy(FieldSerializer.java:271)
    at com.esotericsoftware.kryo.Kryo.copy(Kryo.java:830)
    at pt.ptinovacao.deepcloner.tests.TesteKryoEmptyEnumMap.main(TesteKryoEmptyEnumMap.java:46)

I attach the file with this change.

Thanks for the help.

Original comment by agentilr...@gmail.com on 26 Sep 2013 at 3:58

Attachments:

GoogleCodeExporter commented 9 years ago
OK, it looks like the EnumMapSerializer class that I mentioned lacks the copy 
method. I was simply overlooked, I guess.

Try to add this lines to this class:

    @Override
     public EnumMap<? extends Enum<?>, ?> copy (Kryo kryo, EnumMap<? extends Enum<?>, ?> original) {
     return new EnumMap(original);
     }

The copy method works fine after it.

P.S. An alternative implementation of copy could simply write the original and 
then read it into a different object. This would work, but would introduce more 
overhead.

@Martin: The above change should probably be included into EnumMapSerializer 
class in your kryo-serializer project. BTW, do other serializers there provide 
a copy method?

Original comment by romixlev on 26 Sep 2013 at 8:54

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Your change resolve my problem!
I checked the copy method was overlooked, as you said.
I just put the copy method and it works! :)

I checked the Martin's project kryo-serializers and none of the classes has the 
copy method implemented. I was having the same problem on 
ArraysAsListSerializer and I write copy method, like that:

        @Override
    public List<?> copy(Kryo kryo, List<?> original) {
        return new ArrayList(original);
    }

Is that ok?

Original comment by agentilr...@gmail.com on 27 Sep 2013 at 12:31

GoogleCodeExporter commented 9 years ago
I'm not sure it is OK to copy lists like you described. The elements of the 
original list will be shared between the new list and the original, IMHO. 
Therefore, if you change some fields for one of the elements in a new list, it 
will also affect the original list. And this is probably not what you'd like to 
have. Therefore, you need to perform a deep-copy, I'd say.

Original comment by romixlev on 27 Sep 2013 at 10:15

GoogleCodeExporter commented 9 years ago
You're right.
Primitive types are copied, other types only copies the reference of the object.

I create a new issue to resolve this new problem.
https://code.google.com/p/kryo/issues/detail?id=135

You can mark this issue as resolved.
Thanks for the help.

Original comment by agentilr...@gmail.com on 27 Sep 2013 at 11:30

GoogleCodeExporter commented 9 years ago

Original comment by romixlev on 27 Sep 2013 at 12:09

GoogleCodeExporter commented 9 years ago
Sorry for missing copy methods in kryo-serializers!

I'm just adding copy to all serializers, once this is finished I'll make a new 
release. I submitted https://github.com/magro/kryo-serializers/issues/15 for 
this.

Original comment by martin.grotzke on 27 Sep 2013 at 12:51

GoogleCodeExporter commented 9 years ago
Hi Martin,

Thanks for creating an issue for this. :)

Original comment by agentilr...@gmail.com on 27 Sep 2013 at 2:28

GoogleCodeExporter commented 9 years ago
I just pushed kryo-serializers-0.24 to sonatype, in some hours it should be in 
maven central.

Original comment by martin.grotzke on 29 Sep 2013 at 10:57