java.lang.NoSuchMethodError: Scala.Predef$.refArrayOps 在 Spark 作业中使用 Scala

Posted

技术标签:

【中文标题】java.lang.NoSuchMethodError: Scala.Predef$.refArrayOps 在 Spark 作业中使用 Scala【英文标题】:java.lang.NoSuchMethodError: scala.Predef$.refArrayOps in Spark job with Scala 【发布时间】:2020-08-23 18:34:48 【问题描述】:

完全错误:

线程“主”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 相关的所有内容:

然后我做了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 。罐 )

版本似乎匹配...

这是我的 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'


构建(胖)罐子:

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's download page 中,只有一个Spark distribution for Scala 2.12,而且它没有 Hadoop;这是否意味着我必须在 gradle.build 中从 2.12 降级到 2.11?

【问题讨论】:

你可以尝试使用compile关键字指定scala版本un gradle构建文件,看这里:***.com/questions/44374472/… 是的,尝试一下,尝试在你的 gradle.build 文件中更改 scala 版本 @Chema 但没有办法保留 Scala 2.12 吗? Scala 2.12 的 Spark(带有 Hadoop)分布? 确实,2.4.5 spark 版本推荐使用 2.12 scala 版本,2.11 已弃用,你试过用 2.11 scala 版本运行你的代码吗?我想知道。 @Chema,它适用于 2.11,我正试图让它以相反的方式工作(使用 2.12) 【参考方案1】:

我会尝试spark-submit --version 来了解scala version 使用的是什么spark

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 version

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

OS 可能正在使用其他 scala version,在我的例子中你可以看到 spark scala versionOS scala version 是不同的

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

注意 来自 O'Really Learning Spark “Holden Karau、Andy Konwinski、Patrick Wendell 和 Matei Zaharia”

依赖冲突

处理dependency conflicts 时偶尔会出现的一个破坏性问题是: 用户应用程序和Spark 本身都依赖于同一个库。这出现了 相对很少,但当它发生时,它可能会让用户感到烦恼。通常,这将体现 当NoSuchMethodErrorClassNotFoundException 或其他一些 在执行Spark 作业期间抛出与类加载相关的JVM exception。 这个问题有两种解决方案。首先是将您的应用程序修改为 依赖于与Spark 相同的third-party library 版本。第二个是 使用通常称为的过程修改应用程序的打包 “阴影。” Maven 构建工具通过高级配置支持着色 例 7-5 中显示的插件(实际上,shading 能力就是为什么插件 被命名为maven-shade-plugin)。 阴影允许您制作第二个副本 不同命名空间下的冲突包并重写应用程序的代码 使用重命名的版本。这种有点brute-force 的技术在 解析运行时dependency conflicts。有关如何遮蔽的具体说明 依赖项,请参阅构建工具的文档。

【讨论】:

以上是关于java.lang.NoSuchMethodError: Scala.Predef$.refArrayOps 在 Spark 作业中使用 Scala的主要内容,如果未能解决你的问题,请参考以下文章