Spark项目报NoSuchMethodError: org.apache.hadoop.conf.Configuration.getPassword如何解决
Spark NoSuchMethodError: org.apache.hadoop.conf.Configuration.getPassword 问题排查方案
报错诱因
该异常属于典型的编译期与运行期依赖版本不一致问题,根因如下:
- 编译阶段你依赖的Hadoop 3.2.0版本中,
org.apache.hadoop.conf.Configuration类确实存在getPassword(String)返回char[]的方法,但运行时类加载器优先加载了无该方法的低版本Hadoop common包 - 你单步调试时能确认方法存在,恰恰说明调试环境和最终运行可执行JAR的环境类路径存在差异
- 你提到运行时会额外加载其他JAR到类路径,这是冲突的核心来源:额外加载的JAR包中携带了低版本Hadoop common,且类加载顺序优先于你可执行JAR中打包的3.2.0版本Hadoop依赖
- 额外可能来源:M1芯片的Mac如果本地配置了Hadoop环境变量,系统CLASSPATH中的低版本Hadoop也可能被优先加载,不受本地Maven仓库清理操作的影响
解决方案
按优先级从上到下尝试即可:
- 调整类加载优先级
如果你使用spark-submit提交作业,添加以下参数强制优先加载用户JAR中的依赖:
如果是直接运行可执行JAR,启动时显式指定类路径优先级:spark-submit --conf spark.driver.userClassPathFirst=true --conf spark.executor.userClassPathFirst=true <你的其他提交参数>java -jar 你的可执行JAR.jar -Djava.class.path=你的可执行JAR.jar - 定位冲突的低版本Hadoop包
在你的Main类入口最开头添加以下代码,打印运行时所有加载的JAR路径,找到所有携带org.apache.hadoop.conf.Configuration类的低版本JAR,删除即可:ClassLoader classLoader = ClassLoader.getSystemClassLoader(); URL[] urls = ((URLClassLoader) classLoader).getURLs(); for (URL url : urls) { System.out.println("加载的JAR:" + url.getFile()); } - 打包时排除传递的低版本Hadoop依赖
如果确认是某个第三方依赖引入了低版本Hadoop,在pom.xml中给对应依赖添加排除规则:<dependency> <groupId>冲突依赖的groupId</groupId> <artifactId>冲突依赖的artifactId</artifactId> <version>对应版本号</version> <exclusions> <exclusion> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> </exclusion> <!-- 其他有冲突的Hadoop相关依赖也可在此处一起排除 --> </exclusions> </dependency> - 屏蔽本地环境的Hadoop变量
运行程序前先执行命令清空Hadoop相关环境变量,避免系统自带的Hadoop包被加载:
再启动你的可执行JAR即可。unset HADOOP_HOME HADOOP_CONF_DIR CLASSPATH
内容的提问来源于stack exchange,提问作者Martin Wunderlich
相关产品推荐
相关产品推荐

