Spark - 任务不可序列化:java.io.NotSerializableException:java.lang.reflect.Field

时间:2017-05-14 02:03:28

标签: java apache-spark serialization kryo

我的一个火花工作错误 -

  

任务不可序列化:java.io.NotSerializableException:   java.lang.reflect.Field中

我意识到我在其中一个闭包中有一个类,它使用了一个java.lang.reflect.Field数组在内存中。由于java.lang.reflect.Field没有实现java.io.Serializable,因此无法通过Spark序列化,从而导致错误。我该如何解决这个错误?不可能不使用Field。

  1. 在每个执行程序中创建一个新的类实例,使其不被序列化。我使用了https://www.nicolaferraro.me/2016/02/22/using-non-serializable-objects-in-apache-spark/,它似乎适用于一种对象类型,但不适用于两种。
  2. 使用Kryo序列化程序为我的班级使用Field - 这会有用吗? Kryo是否适用于不实现java.io.Serializable。
  3. 的类
  4. 使用广播变量 - 我不确定这一点。广播变量是否必须可序列化?
  5. 当一个对象因某种原因无法被序列化时,有什么其他方法可以解决这个NotSerializableException。

1 个答案:

答案 0 :(得分:0)

  

不可能不使用Field?

如果不了解您的代码以及您使用这些Field实例的内容,我们无法回答这个问题。 (显然!)

但这可能是错误的问题。您可能应该问的问题是,是否可以避免序列化Field个对象。答案是肯定的。

  • 您可以将字段标记为transient。这意味着他们不会被序列化。如果Field引用只是缓存信息,只需查看它们并再次缓存它们......如果需要它们。

  • 您可以将自定义序列化方法添加到Field字段所属的类中。这些可以将字段名称/签名/任何内容序列化为字符串数据,然后在反序列化数据时尝试再次(通过类API)解析它们。实际上,您尝试在要反序列化的上下文中找到等效的 Field对象。

我怀疑Kryo或广播变量(无论它们是什么)。 Field基本上是不可序列化的,因为它依赖于不可传输的JVM状态(类标识)。

完全避免序列化的方案可能会起作用,具体取决于应用程序如何使用这些对象。

  

当一个类真正无法序列化时,我正在寻找解决NotSerializableException的输入。

好吧,我认为如果不可能以任何方式序列化对象,你就会问该怎么办;例如自定义序列化方法不起作用,Kryo不起作用,没有别的方法可行。 (我很确定如果自定义序列化或Kryo都不起作用,那么其他任何东西都不会起作用。)

如果对象的序列化选项都不起作用,那么您只能做一件事。不要将它序列化。

请注意,有些课程确实如此;例如线程和许多Swing和AWT类从根本上是不可序列化的。