IntelliJ运行Hadoop WordCount遇NullPointerException求助
问题背景
首次使用Java和Hadoop,在IntelliJ中运行WordCount程序,已确认安装Maven、Hadoop 2.7.2、Java 1.8 JDK,代码无语法错误,但运行时抛出NullPointerException,异常栈如下:
Exception in thread "main" java.lang.NullPointerException at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1092) at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073) at org.apache.hadoop.util.Shell.runCommand(Shell.java:483) at org.apache.hadoop.util.Shell.run(Shell.java:456) at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:722) at org.apache.hadoop.util.Shell.execCommand(Shell.java:815) at org.apache.hadoop.util.Shell.execCommand(Shell.java:798) at org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:731) at org.apache.hadoop.fs.RawLocalFileSystem.mkOneDirWithMode(RawLocalFileSystem.java:489) at org.apache.hadoop.fs.RawLocalFileSystem.mkdirsWithOptionalPermission(RawLocalFileSystem.java:530) at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:507) at org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:305) at org.apache.hadoop.mapreduce.JobSubmissionFiles.getStagingDir(JobSubmissionFiles.java:133) at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:144) at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290) at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287) at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) at java.base/javax.security.auth.Subject.doAs(Subject.java:533) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657) at org.apache.hadoop.mapreduce.Job.submit(Job.java:1287) at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1308) at tn.insat.tp1.WordCount.main(WordCount.java:23)
项目类结构:tn.insat.tp1包下包含WordCount、TokenizerMapper、IntSumReducer三个类。
项目文件内容
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hadoop.mapreduce</groupId> <artifactId>wordcount</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>19</maven.compiler.source> <maven.compiler.target>19</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-core</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-common</artifactId> <version>2.7.2</version> </dependency> </dependencies> </project>
TokenizerMapper.java
package tn.insat.tp1; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; import java.util.StringTokenizer; public class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(Object key, Text value, Mapper.Context context ) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } }
IntSumReducer.java
package tn.insat.tp1; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable(); public void reduce(Text key, Iterable<IntWritable> values, Context context ) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { System.out.println("value: "+val.get()); sum += val.get(); } System.out.println("--> Sum = "+sum); result.set(sum); context.write(key, result); } }
WordCount.java
package tn.insat.tp1; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class WordCount { public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1);}}
解决思路
修正JDK版本不匹配问题:Hadoop 2.7.2仅支持Java 7/8,但你的
pom.xml配置了编译版本19,会引发兼容性错误。修改pom.xml中的编译参数为1.8:<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>同时在IntelliJ中设置项目SDK为Java 1.8:
File -> Project Structure -> Project -> SDK选择对应版本。配置Hadoop环境变量:确保系统中正确配置
HADOOP_HOME指向Hadoop安装目录,并将$HADOOP_HOME/bin和$HADOOP_HOME/sbin(Windows为%HADOOP_HOME%\bin和%HADOOP_HOME%\sbin)加入PATH。终端执行hadoop version验证配置有效性。添加运行参数:
WordCount依赖命令行参数传入输入输出路径。在IntelliJ的运行配置中,打开Run -> Edit Configurations,在Program arguments中输入:/本地输入文件路径 /本地输出目录(输出目录必须是不存在的空目录)。检查Hadoop服务状态(分布式模式):如果提交到集群运行,需确保HDFS和YARN服务已启动。执行
start-dfs.sh和start-yarn.sh(Windows为.cmd脚本),用jps命令查看NameNode、DataNode、ResourceManager、NodeManager进程是否正常运行。修复权限问题:异常显示创建临时目录时权限不足,需确保运行IntelliJ的用户对Hadoop临时目录(默认
/tmp/hadoop-${user})有读写权限,同时输入输出路径的权限配置正确。
内容的提问来源于stack exchange,提问作者Aris

