火花对象不可序列化

时间:2018-01-10 08:20:16

标签: scala apache-spark

有没有想过为什么整个对象B需要被序列化?

object A{

  def main(args:Array[String])= {
    val conf = new SparkConf().setAppName("test").setMaster("local")
    val sc = new SparkContext(conf)
    val rdd=sc.makeRDD(Seq(1,2,3,4,5,6,7))
    val b=new B
    b.add(rdd)
  }
}
class B {

  val s="456"
  def add=(rdd:RDD[Int])=>{
    rdd.map(e=>e+" "+s).foreach(println)
  }
}

关于“对象不可序列化”的例外情况:

Serialization stack:
- object not serializable (class: B, value: B@1fde4f40)
- field (class: B$$anonfun$add$1, name: $outer, type: class B)
- object (class B$$anonfun$add$1, <function1>)
- field (class: B$$anonfun$add$1$$anonfun$apply$1, name: $outer, type: class B$$anonfun$add$1)
- object (class B$$anonfun$add$1$$anonfun$apply$1, <function1>)

1 个答案:

答案 0 :(得分:1)

请参阅链接的Task not serializable: java.io.NotSerializableException when calling function outside closure only on classes not objects。你的语法是什么

def add=(rdd:RDD[Int])=>{
  rdd.map(e=>e+" "+s).foreach(println)
}

真的意味着

def addReal(): RDD[Int] => Unit = (rdd: RDD[Int]) => {
  val rddFunc: Int => String = e => e + " " + s
  rdd.map(rddFunc).foreach(println)
}

现在rddFunc captures s来自其包含对象B的上下文,这是通过实际捕获整个对象B来完成的序列化的。

除了链接答案中列出的选项之外,还有什么可以帮助您将add更改为

def add(rdd:RDD[Int]) = {
  val localS = s
  rdd.map(e => e + " " + localS).foreach(println)
}

主要技巧是引入localS变量,强制rddFunc仅捕获它而不是整个B

旁注 :在上面的代码中,我还更改了add的签名

def add():Function1[RDD[Int], Unit]  

你必须

def add(rdd:RDD[Int]):Unit

add返回您立即致电的功能的情况下,没有任何好处。