5

我写了一个用 sbt 构建的 spark 流应用程序。它在本地工作得很好,但是在集群上部署之后,它抱怨我在胖 jar 中清楚地写了一个类(使用 jar tvf 检查)。以下是我的项目结构。XXX对象是spark抱怨的对象

src
`-- main
    `-- scala
        |-- packageName
        |   `-- XXX object
        `-- mainMethodEntryObject

我的提交命令:

$SPARK_HOME/bin/spark-submit \
  --class mainMethodEntryObject \
  --master REST_URL\
  --deploy-mode cluster \
  hdfs:///FAT_JAR_PRODUCED_BY_SBT_ASSEMBLY

具体报错信息:

java.lang.NoClassDefFoundError: Could not initialize class XXX
4

3 回答 3

3

我遇到这个问题的原因类似于这个用户: http ://apache-spark-developers-list.1001551.n3.nabble.com/java-lang-NoClassDefFoundError-is-this-a-bug-td18972.html

我在一个对象上调用一个方法,该对象本身定义了一些变量,包括火花和记录器,就像这样

val spark = SparkSession
  .builder()
  .getOrCreate()

val logger = LoggerFactory.getLogger(this.getClass.getName)

我正在调用的函数在对象上调用了另一个函数,该函数调用了另一个函数,该函数在对flatMaprdd 的调用中调用了对象上的另一个函数。

我在堆栈跟踪中遇到NoClassDefFoundError错误,其中堆栈跟踪中的前 2 个函数调用是 Spark 告诉我的类上的函数不存在。

根据上面链接的对话,我的假设是,在调用使用它的函数(导致异常spark的那个)时,全局引用没有被初始化。NoClassDefFoundError

经过相当多的实验,我发现这种模式可以解决问题。

// Move global definitions here
object MyClassGlobalDef {

  val spark = SparkSession
    .builder()
    .getOrCreate()

  val logger = LoggerFactory.getLogger(this.getClass.getName)

}

// Force the globals object to be initialized
import MyClassGlobalDef._

object MyClass {
  // Functions here
}

这有点难看,但 Spark 似乎喜欢它。

于 2018-05-29T17:25:49.130 回答
2

没有代码很难说,但它看起来像是你的 XXX 对象的序列化问题。我不能说我完全理解为什么,但关键是对象没有被运送给执行者。

对我有用的解决方案是将您的对象转换为扩展的类,Serializable并在您需要的地方实例化它。所以基本上,如果我没记错的话,你有

object test {
   def foo = ...
}

这将用作test.foo您的主要内容,但您至少需要

class Test extends Serializable {
   def foo = ...
}

然后在你的主要有val test = new Test开始,就是这样。

于 2017-12-08T20:51:22.297 回答
1

它与序列化有关。我通过向给定类添加“实现可序列化”和 serialVersionUID 字段来解决此问题。

于 2021-01-12T09:06:43.597 回答