当我使用kryo反序列化ArrayList对象时,我得到一个NullPointerException。
Caused by: java.lang.NullPointerException
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:215)
at java.util.ArrayList.ensureCapacity(ArrayList.java:199)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:96)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:22) at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:679)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
我可以看到StdInstantiatorStrategy在不调用其构造函数的情况下创建了一个ArrayList,而其中一个字段未初始化导致异常。
文档说首先应该调用no参数构造函数,如果没有,可以使用StdInstantiatorStrategy来进行字段初始化。
我做错了什么?
答案 0 :(得分:12)
使用kryo 2.24版,调用
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
覆盖使用class no argument构造函数的默认实例化器策略(如果存在)。正确的方法是致电:
((Kryo.DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy()).setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());
这里解释https://github.com/EsotericSoftware/kryo
我认为自2.21版以来这已经发生了变化
答案 1 :(得分:1)
我收到类似的空指针异常,我需要添加一个自定义序列化程序:https://github.com/magro/kryo-serializers
例如:
kryo.register( Collections.EMPTY_LIST.getClass(), new CollectionsEmptyListSerializer() );
答案 2 :(得分:1)
我遇到了同样的问题,终于解决了。就我而言,我在 Spark 作业中使用 protobuf 对象。 Spark kryo 序列化器无法很好地序列化/反序列化 protobuf 对象。我们可以用两种方法来解决这个问题。
rdd[YourProtobufObject]
转换为 rdd[ByteString]
,使用 pb.toByteString()
进行序列化并使用 .parseFrom(xxByteString)
进行反序列化。实际上,这种方法并不优雅,但确实有效。SparkConf
。例如conf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer")
.set("spark.kryo.registrator","your.own.registrator.implement.MyKryoRegistrator")
其次,创建您自己的注册器工具。您可以使用 Twitter 开源 Chill 项目 ProtobufSerializer 依赖项或 mvnrepository,直接使用 ProtobufSerializer
。 maven 依赖看起来像这样。
<dependency>
<groupId>com.twitter</groupId>
<artifactId>chill_2.11</artifactId>
<version>0.9.3</version>
</dependency>
<dependency>
<groupId>com.twitter</groupId>
<artifactId>chill-protobuf</artifactId>
<version>0.9.3</version>
<exclusions>
<exclusion>
<groupId>com.twitter</groupId>
<artifactId>chill-java</artifactId>
</exclusion>
</exclusions>
</dependency>
创建您自己的名为 MyKryoRegistrator
的 kryo 注册器工具
class MyKryoRegistrator extends KryoRegistrator {
override def registerClasses(kryo: Kryo): Unit = {
kryo.register(classOf[YourProtobufObject], new ProtobufSerializer())
}
}
答案 3 :(得分:0)
还要注意如何创建列表,有一些方法可以创建不可修改的列表,这可能会导致这种序列化麻烦。
例如,测试Arrays.asList("a", "b")
中流行的快捷方式可能会出现问题。
解决方法:new ArrayList<>(asList("a", "b"))
。