Spark Scala应用单元测试报java.lang.NoSuchFieldError: JAVA_9求助
问题分析与解决
问题根因
报错java.lang.NoSuchFieldError: JAVA_9本质是依赖冲突:Spark 3.3.2默认依赖Hadoop 3.3.2,该版本的org.apache.hadoop.util.VersionInfo类中定义了JAVA_9常量;但你的项目中可能间接引入了更低版本的Hadoop(比如2.x系列),这类版本的VersionInfo没有JAVA_9字段,导致运行单元测试时JVM找不到该字段抛出错误。
mvn test-compile仅完成编译动作,不会加载运行时依赖,因此不会触发该错误;而mvn install会执行单元测试,此时会加载所有运行时依赖,依赖冲突就会暴露出来。
解决方案
- 统一Hadoop依赖版本:在pom.xml的
<dependencyManagement>中显式指定Spark 3.3.2兼容的Hadoop版本(推荐3.3.2),覆盖间接引入的低版本依赖:<dependencyManagement> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.3.2</version> </dependency> </dependencies> </dependencyManagement> - 排查并排除冲突依赖:执行
mvn dependency:tree命令,查找所有引入Hadoop相关依赖的路径,确认是否有低版本依赖被间接引入,必要时通过<exclusions>排除冲突项:<!-- 示例:排除某依赖中引入的低版本Hadoop --> <dependency> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <version>xxx</version> <exclusions> <exclusion> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> </exclusion> </exclusions> </dependency> - 统一Scala依赖版本:你的pom中scala-reflect版本为2.12.10,而编译用的Scala版本是2.12.18,建议将scala-reflect版本同步为2.12.18,避免版本不一致引发的潜在问题:
<dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-reflect</artifactId> <version>2.12.18</version> </dependency>
关于Java8环境进入该代码分支的疑惑
这个问题和编译时的Java版本无关,而是运行时依赖的代码逻辑导致的:Spark的StorageUtils类在初始化时会调用Hadoop的VersionInfo类获取Java版本相关信息,不管你用Java8还是更高版本编译,只要运行时加载的Hadoop依赖是3.x版本,这段代码就会执行;但如果运行时加载的是低版本Hadoop(没有JAVA_9字段),就会抛出错误。本质是运行时依赖的Hadoop版本不匹配,并非你的应用编译时的Java版本导致进入错误分支。
内容的提问来源于stack exchange,提问作者saravana ir
相关产品推荐
相关产品推荐

