Spark 3.5.1搭配Java 17测试报IllegalAccessError的解决求助
解决方案:Java 17下Spark 3.5.1 IllegalAccessError及反序列化问题
问题根源
Java 17严格限制了对sun.nio.ch等内部API的访问,Spark 3.5.1的StorageUtils类需要调用这些内部API;直接添加单一--add-exports参数会破坏序列化兼容性,触发InvalidObjectException。
通用解决方案(适配SBT、Git Actions等非IDE场景)
1. 完善SBT多阶段JVM参数配置
确保JVM参数覆盖编译、测试、运行全阶段,且参数组合精准。修改build.sbt如下:
name := "spark-java17-project" version := "0.1" scalaVersion := "2.12.12" val sparkVersion = "3.5.1" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-core" % sparkVersion % Provided, "org.apache.spark" %% "spark-sql" % sparkVersion % Provided ) // SBT自身及基础编译阶段的JVM参数 javaOptions ++= Seq( "--illegal-access=permit", "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens=java.base/java.nio=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED" ) // Spark任务运行阶段的独立JVM参数(必须开启fork) fork := true javaOptions in run ++= Seq( "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens=java.base/java.nio=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/java.util=ALL-UNNAMED" ) // 测试阶段的专属参数 javaOptions in Test ++= Seq( "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens=java.base/java.nio=ALL-UNNAMED" )
2. Spark任务提交时显式传递JVM参数
如果通过spark-submit运行任务,需在命令行或代码中指定Driver和Executor的参数:
import org.apache.spark.SparkConf val conf = new SparkConf() .setAppName("TaskDemo") .setMaster("local[*]") .set("spark.driver.extraJavaOptions", "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED") .set("spark.executor.extraJavaOptions", "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED")
3. 修复反序列化错误
出现InvalidObjectException时,通过以下方式解决:
- 确保所有序列化类实现
java.io.Serializable接口 - 启用Spark的Kryo序列化(推荐,兼容性更强):
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") conf.set("spark.kryo.registrationRequired", "false")
4. Git Actions中的配置示例
在.github/workflows/build.yml中注入JVM参数,确保构建测试正常执行:
name: Spark Build & Test on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - name: Build with SBT run: sbt clean test env: JAVA_OPTS: "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --illegal-access=permit"
关键注意点
fork := true必须开启:保证Spark任务运行在独立JVM进程,应用配置的参数- 区分SBT自身参数与Spark任务参数:两者作用的JVM进程不同,需分别配置
- 避免依赖
--illegal-access=permit:Java 17中该参数已废弃,需配合精准的--add-exports/--add-opens授权
内容的提问来源于stack exchange,提问作者Mujtaba Faizi
相关产品推荐
相关产品推荐

