lishunli / kryo

Automatically exported from code.google.com/p/kryo

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

GoogleCodeExporter opened this issue · comments

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

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

  • Added labels: ****
  • Removed labels: ****
> 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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****
[deleted comment]
The attached file

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

  • Added labels: ****
  • Removed labels: ****

Attachments:

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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****

Attachments:

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

  • Added labels: ****
  • Removed labels: ****
[deleted comment]
[deleted comment]
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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****

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

  • Changed state: Fixed
  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****
Hi Martin,

Thanks for creating an issue for this. :)

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

  • Added labels: ****
  • Removed labels: ****
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

  • Added labels: ****
  • Removed labels: ****