我知道有很多关于这个问题,但我没能找到究竟需要可序列化系统的解释(以及何时序列化)......以及如何验证此要求。星火序列化(?)与特质古怪和差异1.6.0之间昂2.1.1
考虑一下:
class Baz
trait Bar { val baz = new Baz; def bar(i: Int) = baz }
case object Foo extends Bar { def foo = sc.parallelize(1 to 1).map(bar).collect }
Foo.foo
这工作,并返回Array(null)
是否有意义给任何人???
如果我改变val
到lazy val
,比停止工作,并抛出NotSerializableException
,这是有道理的 - 它初始化baz
在远程端,然后无法把它送回来。 但是,为什么它在第一种情况下愉快地用null
替代?
如果我写它,好看多了,我能想到的任何其他方式 - 从特质移动bar
定义对象,例如,或者_ => baz
替换bar
调用 - 它也停止工作,并抱怨说Task is not serializable
。
与返回的是一个特征定义的VAL的方法,这使得它只是把它写为null
,而不是这是什么?有任何想法吗?
UPDATE 上述行为发生在scala 2.11和spark 2.1.1上。 斯卡拉2.10(火花1.6.0)不会抛出异常,抱怨Baz
不可序列化......所以,这似乎是一种倒退。
也我注意到,在火花1.6.0,像这样工作得很好:
object Foo { def foo = sc.parallelize(1 to 1).map(bar).collect; def bar(i: Int) = i+1 }
Foo.foo
但在火花2.1.1它抱怨说Foo
是不可序列。这是为什么? 显然,序列化拉姆达想也序列化Foo
,其中排序有道理......但它确实工作在1.6.0不知何故,即使我做labda实际引用其他的事情Foo
:
object Foo {
var stuff = 10
def foo = sc.parallelize(1 to 1).map(bar).collect
def bar(i: Int) = { stuff += 1; i+1 }
}
Foo.foo
Foo.stuff
这工作正常1.6.0,而不是在2.1.1。
所以,这里的一个问题是它如何在实际工作1.6.0?我的意思是,Foo
不是可序列化的,它怎么知道另一端的stuff
的值?
另外,显而易见的,问题是 - 为什么它停止工作2.1.1? 1.6.0行为是否存在微妙的问题,我们是否应该不依赖它? 或者它只是2.1.1中的一个错误?
实际上,我对这些不良的唯一理解就是'val'和'lazy val'情况下的结果不同:) 其他一切似乎都像一大堆......神秘:) – Dima
此外,忘了提及:你写的代码在使用和不使用“懒惰”的情况下的工作方式都是一样的,但它与我的(第一个)代码片段没有做同样的事情。如果你把'foo'改成'sc.parallelize(1 to 1).map(sc.clean(bar))。collect',那么它会以懒惰(这是可以理解的)抛出,但是“工作”并返回一个没有懒惰的_null_数组,这只是没有任何意义。 – Dima