Spark作业中遇到的Scala错误:java.lang.NoSuchMethodError: scala.Predef$.refArrayOps

4
完整错误:

在主线程中发生异常:java.lang.NoSuchMethodError: scala.Predef$.refArrayOps([Ljava/lang/Object;)[Ljava/lang/Object; 在 org.spark_module.SparkModule$.main(SparkModule.scala:62) 中 在 org.spark_module.SparkModule.main(SparkModule.scala) 中 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 中 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 中 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 中 在 java.lang.reflect.Method.invoke(Method.java:498) 中 在 org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52) 中 在 org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:845) 中 在 org.apache.spark.deploy.SparkSubmit.doRunMain$1(SparkSubmit.scala:161) 中 在 org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:184) 中 在 org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86) 中 在 org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:920) 中 在 org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:929) 中 在 org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala) 中

当我在Intellij中编译和运行代码时,一切都很顺利。问题在我将.jar作为spark作业(运行时)提交时出现。
第62行包含:for ((elem, i) <- args.zipWithIndex)。我注释了其余的代码以确保,但是错误仍然显示在那行上。
起初,我认为是zipWithIndex的问题。然后我将其更改为for (elem <- args),猜猜发生了什么,错误仍然显示。是否是for引起的呢?
Google搜索总是指向编译使用的Scala版本与运行时使用的版本不兼容,但我无法找到解决方法。
我尝试了this以检查IntelliJ使用的Scala版本,并且在Modules> Scala 下列出了所有与Scala相关的内容:

enter image description here

然后我执行了this,以检查Scala的运行时版本,输出结果如下:

(file:/C:/Users/me/.gradle/caches/modules-2/files-2.1/org.scala-lang/scala-library/2.12.11/1a0634714a956c1aae9abefc83acaf6d4eabfa7d/scala-library-2.12.11.jar )

版本似乎匹配...

这是我的gradle.build(包括fatJar任务)

group 'org.spark_module'
version '1.0-SNAPSHOT'

apply plugin: 'scala'
apply plugin: 'idea'
apply plugin: 'eclipse'

repositories {
    mavenCentral()
}

idea {
    project {
        jdkName = '1.8'
        languageLevel = '1.8'
    }
}

dependencies {
    implementation group: 'org.scala-lang', name: 'scala-library', version: '2.12.11'
    implementation group: 'org.apache.spark', name: 'spark-core_2.12'//, version: '2.4.5'
    implementation group: 'org.apache.spark', name: 'spark-sql_2.12'//, version: '2.4.5'
    implementation group: 'com.datastax.spark', name: 'spark-cassandra-connector_2.12', version: '2.5.0'
    implementation group: 'org.apache.spark', name: 'spark-mllib_2.12', version: '2.4.5'
    implementation group: 'log4j', name: 'log4j', version: '1.2.17'
    implementation group: 'org.scalaj', name: 'scalaj-http_2.12', version: '2.4.2'
}

task fatJar(type: Jar) {
    zip64 true
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    } {
        exclude "META-INF/*.SF"
        exclude "META-INF/*.DSA"
        exclude "META-INF/*.RSA"
    }

    manifest {
        attributes 'Main-Class': 'org.spark_module.SparkModule'
    }

    with jar
}

configurations.all {
    resolutionStrategy {
        force 'com.google.guava:guava:12.0.1'
    }
}

compileScala.targetCompatibility = "1.8"
compileScala.sourceCompatibility = "1.8"

jar {
    zip64 true
    getArchiveFileName()
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    manifest {
        attributes 'Main-Class': 'org.spark_module.SparkModule'
    }

    exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'

}

构建(fat)jar文件:
gradlew fatJar

在IntelliJ的终端中。 运行该作业:
spark-submit.cmd .\SparkModule-1.0-SNAPSHOT.jar

在Windows PowerShell中。

谢谢。

编辑:

spark-submit.cmdspark-shell.cmd都显示Scala版本2.11.12,所以是的,它们与我在IntelliJ中使用的版本(2.12.11)不同。问题是,在Spark下载页面中,只有一个Scala 2.12的Spark发行版,并且没有Hadoop;这是否意味着我必须将gradle.build中的Scala版本从2.12降级到2.11?


1
你可以在Gradle构建文件中使用compile关键字来指定Scala版本,参考这里:https://dev59.com/EaLia4cB1Zd3GeqPhVV9 - Boris Azanov
是的,确切地说,请尝试在您的gradle.build文件中更改scala版本。 - Chema
实际上,在2.4.5版本的Spark中,建议使用2.12版本的Scala,而2.11已经被弃用了。你尝试过使用2.11版本的Scala运行你的代码吗?我想知道。 - Chema
@Chema,它在2.11上运行正常,我正在尝试让它在另一个版本(2.12)上运行。 - Scaramouche
你的代码运行得很好!我更新了我的答案并添加了一些注释! - Chema
显示剩余2条评论
1个回答

4
我会尝试运行 spark-submit --version 命令来查看 spark 使用的 scala版本
使用 spark-submit --version 命令,我可以获取以下信息。
[cloudera@quickstart scala-programming-for-data-science]$ spark-submit --version
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 2.2.0.cloudera4
      /_/
                        
Using Scala version 2.11.8, Java HotSpot(TM) 64-Bit Server VM, 1.8.0_202
Branch HEAD
Compiled by user jenkins on 2018-09-27T02:42:51Z
Revision 0ef0912caaab3f2636b98371eb29adb42978c595
Url git://github.mtv.cloudera.com/CDH/spark.git
Type --help for more information.

spark-shell 中可以尝试以下命令来查询 Scala 版本

scala> util.Properties.versionString
res3: String = version 2.11.8

操作系统可能正在使用其他的scala版本,在我的情况下,你可以看到Spark Scala版本操作系统Scala版本是不同的。

[cloudera@quickstart scala-programming-for-data-science]$ scala -version
Scala code runner version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.

Note 来自O'Really Learning Spark的消息“Holden Karau,Andy Konwinski,Patrick Wendell和Matei Zaharia”

依赖冲突

处理依赖冲突问题是一个偶尔会引起干扰的问题,在这种情况下,用户应用程序和Spark本身都依赖于同一库。这种情况相对较少,但当出现时,可能会让用户感到困扰。通常,当执行Spark作业时,会抛出NoSuchMethodErrorClassNotFoundException或其他与类加载有关的JVM异常,从而表明此问题存在。解决此问题有两个方法。第一种方法是修改应用程序,以依赖于Spark所依赖的第三方库的相同版本。第二种方法是使用通常称为“shading”的过程修改应用程序的打包。Maven构建工具通过Example 7-5中显示的插件的高级配置支持阴影技术(实际上,阴影功能是插件被命名为maven-shade-plugin的原因)。 Shading允许你在不同的命名空间下制作一个冲突软件包的第二个副本,并重新编写应用程序的代码以使用重命名版本。这种有点强制性的技术相当有效地解决了运行时的依赖冲突问题。有关如何使用阴影技术的具体说明,请参见您的构建工具的文档。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接