Java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession 这段文字意味着找不到名为"org/apache/spark/sql/SparkSession"的类。

26

我已经用Java编写了一个Spark作业。当我提交作业时,它会出现以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession
        at com.thinkbiganalytics.veon.util.SparkSessionBuilder.getOrCreateSparkSession(SparkSessionBuilder.java:12)
        at com.thinkbiganalytics.veon.AbstractSparkTransformation.initSparkSession(AbstractSparkTransformation.java:92)
        at com.thinkbiganalytics.veon.transformations.SDPServiceFeeDeductionSourceToEventStore.init(SDPServiceFeeDeductionSourceToEventStore.java:57)
        at com.thinkbiganalytics.veon.AbstractSparkTransformation.doTransform(AbstractSparkTransformation.java:51)
        at com.thinkbiganalytics.veon.transformations.SDPServiceFeeDeductionSourceToEventStore.main(SDPServiceFeeDeductionSourceToEventStore.java:51)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:745)
        at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181)
        at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206)
        at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121)
        at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.spark.sql.SparkSession
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

你能否提供你的pom.xml文件(如果你使用Maven)或者build.gradle文件(如果你使用Gradle)呢?这将使这个问题对其他用户更有帮助。 - AztecCodes
13个回答

34

如果你在 Intellij IDEA 中运行,并将你的 Spark 库标记为“提供的”,例如:"org.apache.spark" %% "spark-sql" % "3.0.1" % "provided",那么你需要编辑你的运行/调试配置并勾选“包括提供范围的依赖项”框。


20
我在从Intellij编辑器中运行时遇到了这个问题。我已经在pom.xml中将Spark库标记为提供的,请参见下文:
<dependency>
     <groupId>org.apache.spark</groupId>
     <artifactId>spark-sql_2.11</artifactId>
     <version>2.4.0</version>
     <scope>provided</scope>
 </dependency>

取消提供的作用域后,错误已消失。

创建提供的 Spark Jars 后,只有在使用 spark-submit 运行应用程序或将 Spark Jars 放在类路径上时才会提供。


做到了!我将它从sparkml示例中复制粘贴过来,就是其中的作用域变量让我出了问题。谢谢。 - Sanjay Verma
2
请遵循此答案 - https://dev59.com/ElcO5IYBdhLWcg3wrTgs#66510343 - OneCricketeer

10

使用 spark-submit 提交时,请检查您的项目在 pom.xml 中的依赖与 Spark 版本相同,

这可能是因为您在同一台机器上安装了两个 Spark 版本


如果您想在计算机上拥有不同的 Spark 安装版本,则可以创建不同的软链接,并使用您构建项目所用的确切 Spark 版本。

spark1-submit -> /Users/test/sparks/spark-1.6.2-bin-hadoop2.6/bin/spark-submit

spark2–submit -> /Users/test/sparks/spark-2.1.1-bin-hadoop2.7/bin/spark-submit

这是Cloudera博客中关于多个Spark版本的链接 https://community.cloudera.com/t5/Advanced-Analytics-Apache-Spark/Multiple-Spark-version-on-the-same-cluster/td-p/39880


注:该链接介绍了如何在同一集群上使用多个Spark版本。

8
如果您在IntelliJ中运行,请按以下方式检查“包含提供范围的依赖项”:
在“运行/调试配置”内选择“修改选项”,然后勾选“包含提供范围的依赖项”。
请参见下图:

Inside Run/Debug Configuration please select for Modify Options and then check


7

可能你正在低版本的Spark集群上部署应用程序。

请检查您的集群中的Spark版本 - 它应该与pom.xml中的版本相同。当使用spark-submit来部署应用程序时,请注意将所有Spark依赖项标记为provided


我需要在哪个文件中将Spark依赖项标记为提供的? - us56
In Maven pom.xml - T. Gawęda
{btsdaf} - Abdul Mannan

2
如果使用Maven,请前往您的依赖项文件(pom.xml)并将作用域从提供(provided)更改为编译(compile)。
<dependency>
   <groupId>org.apache.spark</groupId>
   <artifactId>spark-sql_2.13</artifactId>
   <version>3.3.0</version>
   <scope>compile</scope>
</dependency>

尽量避免这个修改。提供的值不应该改变。如果你想了解更多,请阅读这个答案 - AztecCodes

1
根据您收到的异常,我认为所需的jar文件缺失,您需要将所需的jar文件添加到类路径中,这将解决该问题。 请参考此链接下载所需的jar文件。

我认为没有与Jar相关的问题。因为我之前在同一环境中执行了几个Spark作业,它们都成功运行了。 - us56
@Umar,你在这些作业中使用了SparkSession还是SparkContext?你使用的Spark版本是哪个?你需要添加更多关于你的环境以及如何创建和执行jar文件的信息。 - philantrovert
是的.. 在我的以前的工作中,我使用了Spark Session和Context。我正在使用Spark版本2.1.1,并使用Maven构建Jar文件。 - us56

1

如何解决运行时找不到SparkSession类的问题

我们需要找出为什么在运行时无法访问Spark SQL包中的SparkSession类。

  1. 检查是否缺少依赖项:
    确保在构建文件中将Spark SQL库列为依赖项。如果您使用Gradle,则是build.gradle;如果您使用Maven,则是pom.xml。同时不要使用scope标签。 如果您正在使用Intellij,请在Run/Debug Configuration中激活“Include dependencies with Provided scope”。某种程度上,provided值会产生很大影响。如果想了解更多关于provided值重要性的信息,请阅读此文。然而,有些人声称将pom.xml文件中的provided改为compile可以解决此问题。

Maven pom.xml

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.11</artifactId>
    <version>YOUR-SPARK-VERSION</version>
    <scope>provided</scope>
</dependency>
  • 提交依赖项:

    当您的依赖项未包含在JAR-文件内时,您可以在运行spark-submit时直接使用--jars选项提供Spark SQL JAR

  • spark-submit --class your.main.class --jars /path/to/spark-sql_2.11-[YOUR-SPARK-VERSION].jar your.jar
    
  • 检查类路径:
    确保在运行时通过添加以下代码行,将Spark SQL jar加入类路径:
  • System.out.println(System.getProperty("java.class.path"));
    
    • 检查是否存在多个 Spark 版本:
      我的答案的这部分受到 这个回答 的启发。 在使用 spark-submit 时,请确保您的项目的 pom.xml 与您要部署的 Spark 版本相匹配。在同一台机器上安装多个 Spark 版本经常会导致错误。

      如何管理不同的 Spark 版本:

    • 创建软链接:
      • spark1-submit → /path/to/spark-1.6.2/
      • spark2-submit → /path/to/spark-2.1.1/

    请阅读来自 @ankursingh1000 的 回答 获取更多信息。

    请还要检查一下Spark版本是否匹配,如果有不匹配的地方,请修复。同时确保正确的Scala版本,以便Spark依赖项中的Scala版本后缀与您使用的Scala版本相匹配。
    我知道这个答案来得晚了,但或许我可以帮助到某人。

    1

    1
    请勿上传代码/数据/错误的图像。 - Ferris

    0
    泄漏spark环境的jar包会导致这个问题 如果你使用的是Intellij IDEA,可以按照以下步骤操作: 文件 -> 项目结构 -> 模块 -> spark-examples_2.11 -> 依赖 jar包 -> {spark目录}/spark/assembly/target/scala-2.11/jars/

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