IDEA中以YARN模式运行Hadoop出现ClassNotFoundException问题
问题描述
在单节点伪分布式Hadoop集群上,通过IDEA+Maven构建WordCount项目(依赖hadoop-client:2.7.7),尝试以YARN模式运行时遇到类找不到的问题,具体场景如下:
- IDEA仅配置HDFS(Local模式):仅设置
fs.defaultFS为hdfs://localhost:9000,程序运行正常。 - Jar包+HDFS+YARN模式:代码无硬编码配置,通过
cluster.xml指定HDFS和YARN参数,执行./bin/hadoop -jar test.jar com.example.WordCount -conf cluster.xml,YARN模式运行正常。 - IDEA直接配置HDFS+YARN:代码中添加
mapreduce.framework.name和yarn.resourcemanager.address配置后运行,报错:
java.lang.classNotFoundException: class com.example.WordCount$TokenizerMapper not found
原因分析
YARN模式下,MapReduce的Mapper/Reducer任务会被分发到集群的NodeManager节点执行。直接在IDEA中运行时,Hadoop无法自动获取到包含TokenizerMapper类的Jar包,导致NodeManager节点加载类失败;而通过hadoop jar命令运行时,Hadoop会自动将当前Jar包作为作业依赖分发到所有节点,因此可以正常找到类。
解决方法
方法1:在代码中指定作业Jar包
在WordCount的作业初始化代码中添加配置,让Hadoop明确要分发的Jar包路径:
// 方式一:通过当前类的位置自动关联Jar包(推荐Maven项目使用) job.setJarByClass(WordCount.class); // 方式二:直接指定Jar包的绝对路径(适合已打包好的Jar) // job.setJar("/path/to/your/project/target/test.jar");
setJarByClass会根据WordCount类的类路径自动定位到对应的Jar包,IDEA运行时会识别编译后的输出Jar或类目录,确保NodeManager能获取到包含TokenizerMapper的文件。
方法2:确保内部类为静态类
如果TokenizerMapper是WordCount的内部类,需将其定义为静态内部类,否则非静态内部类依赖外部类实例,NodeManager无法独立加载:
public class WordCount extends Configured implements Tool { // 定义为静态内部类 public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> { // ... 实现代码 } // ... 其他代码 }
方法3:IDEA运行配置中指定Jar包
在IDEA的运行配置中,将项目打包后的Jar包路径添加到Hadoop的作业参数中,确保作业提交时能携带该Jar包。
内容的提问来源于stack exchange,提问作者chenzhongpu

