Java 序列化和Scala的闭包的区别和注意点

背景

最近在做一些scala闭包和java序列化的问题回顾,具体的是Spark DPP(动态分区裁剪)导致的DataSourceScanExec NullPointerException问题分析以及解决
在此记录一下,主要是文章说到的 DataSourceScanExec 中 maxMetadataValueLength字段的序列化和反序列化问题

trait DataSourceScanExec extends LeafExecNode {
  def relation: BaseRelation
  def tableIdentifier: Option[TableIdentifier]

  protected val nodeNamePrefix: String = ""

  override val nodeName: String = {
    s"Scan $relation ${tableIdentifier.map(_.unquotedString).getOrElse("")}"
  }

  // Metadata that describes more details of this scan.
  protected def metadata: Map[String, String]

  protected val maxMetadataValueLength = sqlContext.sessionState.conf.maxMetadataStringLength
  ...

在这里说到了DataSourceScanExec的实现类FileSourceScanExecdoCanonicalize方法会new FileSourceScanExec对象(这里会在Executor调用),所以导致 maxMetadataValueLength这行代码报空指针问题,因为 sqlContext 标记为了@transient,这样在新建该对象的时候就会初始化 maxMetadataValueLength ,所以就NPE了,
而之所以不会再Executor反序列化RDD的时候报错,是因为 maxMetadataValueLength 在序列化的时候,获取的值是 具体的整数值,会直接把该整数值给序列化,这样在反序列化的时候,直接获取的就是对应的整数值。

Java序列化

java序列化的时候,只会序列化实例变量所引用的对象,如

SparkConf confRef = conf	

如果是以下这种就不会序列化对应的SparkConf对象:

int maxMetadataValueLength = conf.maxMetadataStringLength	

这是因为该maxMetadataValueLength已经获取到了对应的整数类型值了,不需要conf了。

Scala闭包

什么是Scala闭包

Scala 闭包是一种函数,它能够捕获并包含其定义环境中的自由变量,使其在函数外部的作用域结束后依然可用。 闭包由两部分组成:一个函数和该函数引用的外部变量。 这种机制允许函数访问和操作其定义时所在的上下文变量,即使在调用该函数时外部变量已经超出作用域

如果此时你这么定义:

val conf = new SparkConf().set("key", "value")

val processFunc = (x: Int) => {
  val maxMetadataValueLength = conf.maxMetadataStringLength  // 闭包内部定义
  x + maxMetadataValueLength
}

这个时候闭包就会引用conf 对象,也就是说该conf对象会在闭包中存在一个成员变量并引用该对象。在spark中 ClosureCleaner 会 clone 一份该对象。
那如何规避,在闭包中不引用该对象呢:
可以通过 预计算值方法,如下:

val conf = new SparkConf().set("key", "value")
val maxMetadataValueLength = conf.maxMetadataStringLength  // 先计算

val processFunc = (x: Int) => {
  x + maxMetadataValueLength  // 闭包只引用值,不引用 conf
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值