You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apache Spark打包Jar运行时出现ClassNotFoundException问题

解决Spark CSV数据源ClassNotFoundException问题

这个问题我之前帮同事排查过好几次,本质就是Spark的CSV数据源模块没被正确打包进你的fat jar里。在Eclipse里运行时,IDE会自动把所有依赖(包括Spark的CSV扩展模块)加载到类路径,但打包成单一jar时,如果依赖配置不对,这个非核心的数据源模块就会被漏掉——毕竟Spark核心包本身不包含CSV、JSON这类第三方数据源的实现,它们是通过Java的ServiceLoader机制动态加载的。

下面分几种场景给你具体的解决方案:

方案1:Maven项目(最常用)

如果你用Maven管理项目,需要两步调整:

1. 确保依赖配置正确

在pom.xml里添加Spark SQL的依赖,不要设置为provided(因为你是本地用java -jar直接运行,不是提交到Spark集群):

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.12</artifactId>
    <version>你的Spark版本,比如3.3.0</version>
</dependency>
<!-- 如果你用的是Spark 1.x版本,需要替换成databricks的spark-csv依赖:
<dependency>
    <groupId>com.databricks</groupId>
    <artifactId>spark-csv_2.11</artifactId>
    <version>1.5.0</version>
</dependency>
-->

2. 修改Shade插件配置(关键!)

Maven的maven-shade-plugin默认会覆盖META-INF/services目录下的文件,而Spark正是通过这个目录下的配置文件来发现数据源的。所以必须添加合并规则:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <!-- 替换成你的主类全路径 -->
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.yourcompany.YourSparkMainClass</mainClass>
                            </transformer>
                            <!-- 合并ServiceLoader配置文件,这一步不能少 -->
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

修改完后执行mvn clean package,用生成的jar包重新运行java -jar命令即可。

方案2:Gradle项目

如果是Gradle项目,同样要注意依赖和打包配置:

1. 配置依赖

在build.gradle里添加Spark SQL依赖:

dependencies {
    implementation 'org.apache.spark:spark-sql_2.12:3.3.0'
    // Spark 1.x版本用这个:
    // implementation 'com.databricks:spark-csv_2.11:1.5.0'
}

2. 配置Shadow插件

使用Gradle的Shadow插件来打包fat jar,并且开启服务文件合并:

plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

shadowJar {
    // 替换成你的主类全路径
    mainClassName = 'com.yourcompany.YourSparkMainClass'
    // 合并ServiceLoader配置文件
    mergeServiceFiles()
}

执行./gradlew shadowJar,然后运行java -jar build/libs/你的项目名称-all.jar就可以解决问题。

方案3:手动排查打包问题

如果以上配置都做了还是报错,可以手动检查你的fat jar:

  • 解压jar包,确认里面存在org/apache/spark/sql/execution/datasources/csv/CSVDataSource.class(对应Spark 2.x+版本)
  • 查看META-INF/services/org.apache.spark.sql.sources.DataSourceRegister文件,确认里面包含org.apache.spark.sql.execution.datasources.csv.CSVDataSource这一行

另外提醒一句:如果你是把jar包提交到Spark集群运行,那依赖可以设为provided,但本地直接用java -jar运行时,必须把Spark的核心依赖和数据源模块都打包进去。

内容的提问来源于stack exchange,提问作者user9642332

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:49:34