Spark单元测试(ScalaTest)执行报java.lang.ExceptionInInitializerError
问题根因
该报错由Hadoop低版本与高版本JDK不兼容导致:Spark 2.4.8默认依赖的Hadoop 2.x内核中,org.apache.hadoop.util.Shell类获取操作系统版本的逻辑存在硬编码缺陷,会强制截取版本号前3位,当JDK 11及以上版本返回的系统版本号长度不足3位时,就会触发字符串下标越界异常。
排查步骤
- 验证当前运行环境的JDK版本:执行
java -version,确认是否为JDK 11/13/17等高版本 - 验证项目依赖的Hadoop版本:执行
mvn dependency:tree | grep hadoop-common,确认hadoop-common版本是否低于2.8.5
解决方案
可根据实际场景选择以下任意一种方案解决:
- 切换运行JDK版本到JDK 8
Spark 2.4.x系列官方仅适配JDK 8,切换JDK版本后重新执行mvn clean install即可正常运行,是成本最低的解决方案。 - 单元测试添加系统参数覆盖版本检测逻辑
在scalatest-maven-plugin的配置中添加自定义系统参数,绕过Hadoop的版本校验:
<plugin> <groupId>org.scalatest</groupId> <artifactId>scalatest-maven-plugin</artifactId> <version>1.0</version> <configuration> <systemProperties> <property> <name>os.version</name> <value>10.0</value> </property> <property> <name>hadoop.home.dir</name> <value>./tmp/hadoop</value> </property> </systemProperties> </configuration> <executions> <execution> <id>test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin>
- 显式引入兼容高版本JDK的Hadoop依赖
在pom.xml的依赖节点中添加更高版本的Hadoop依赖,覆盖Spark传递的旧版本:
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.8.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.8.5</version> <scope>test</scope> </dependency>
- Windows环境额外处理
如果在Windows系统运行,还需要下载对应Hadoop版本的winutils.exe文件,放到上述配置的hadoop.home.dir的bin目录下,避免NativeCodeLoader相关的后续报错。
内容的提问来源于stack exchange,提问作者Ayan Biswas
相关产品推荐
相关产品推荐

