【问题标题】:In scala, how to declare a nested class to be transient?在scala中,如何将嵌套类声明为瞬态?
【发布时间】:2018-04-11 17:56:21
【问题描述】:

我有一个包含隐式转换的实用程序对象:

object Util {

  implicit class SparkView(sc: SparkContext) {

    def do(): Unit = sc.parallelize(1 to 10).foreach {
      doSomething()
    }
  }

  def doSomething(): Unit
}

开箱即用:

val sc = new SparkContext()
sc.do()

但是,当我将上述 Util 实现更改为稍有不同时:

class Util {

  implicit class SparkView(sc: SparkContext) {

    def do(): Unit = sc.parallelize(1 to 10).foreach {
      doSomething()
    }
  }

  def doSomething(): Unit
}
case object Util extends Util

它的相同用法给出以下错误:

> Task not serializable org.apache.spark.SparkException: Task not
> serializable  at
> org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:340)
>   at
> org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:330)
>   at
> org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:156)
>  ...
> Caused by: java.io.NotSerializableException:
> my.package.Util$SparkView
> Serialization stack:
>   - object not serializable (class: my.package.Util$SparkView, value:
> my.package.Util$SparkView@4f03729f)

事实证明,在第二种情况下,函数 doSomething() 被序列化并附带了无用的东西(实际的函数签名变为this.$outer.doSomething())。一个直接的解决方法是将 SparkView 的所有实例声明为瞬态,这样它就不会被序列化和交付,并且可以从单例 Util 中从头开始读取函数 doSomething。我应该如何轻松实现?

【问题讨论】:

    标签: scala apache-spark serialization


    【解决方案1】:

    Spark ClosureCleaner 不是序列化闭包的可靠工具。 Closure 将this 连同所有字段一起捕获,然后 ClosureCleaner 尝试使用一些没有保证的启发式方法来取消未使用的字段。

    所以只要保持范围小,代码简单,希望它能工作。

    您也不能使SparkView 瞬态,因为瞬态是字段的属性,而不是对象。

    【讨论】:

      猜你喜欢
      • 2019-03-23
      • 2012-05-31
      • 1970-01-01
      • 2010-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多