WSL下VSCode运行Hadoop Java程序遇NoClassDefFoundError求助
问题描述
我是Hadoop和Java纯新手,已在WSL中配置伪分布式Hadoop,现通过WSL内的VSCode运行Java示例程序,已添加所需参考库和Hadoop配置文件,但执行Configuration conf = new Configuration();时出现以下错误:
liu@liu:~/bigdata/proj1$ cd /home/liu/bigdata/proj1 ; /usr/bin/env /usr/local/jdk8/bin/java -cp /tmp/cp_9uebk944mttbxgu829j50i3s5.jar CopyFromLocalFile Exception in thread "main" java.lang.NoClassDefFoundError: com/ctc/wstx/io/InputBootstrapper at CopyFromLocalFile.main(CopyFromLocalFile.java:61) Caused by: java.lang.ClassNotFoundException: com.ctc.wstx.io.InputBootstrapper at java.net.URLClassLoader.findClass(URLClassLoader.java:387) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 1 more
请问这是否和WSL有关?为何已添加所需库仍报错?该如何解决?
附相关配置文件
1. .vscode下的task.json
{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "label": "hadoop - start service", "type": "shell", "command": "start-all.sh", "options": { "cwd": "${workspaceFolder}" }, "group": "build" }, { "label": "hadoop - build & run", "type": "shell", "command": "mkdir /tmp/a2f2ed || : && javac -cp $(hadoop classpath) -d /tmp/a2f2ed ${file} && jar -cvf bin/test.jar -C /tmp/a2f2ed . && rm -rf /tmp/a2f2ed || :&& hdfs dfs -rm -r /input || : && hdfs dfs -put input / && hdfs dfs -rm -r /output || :&& hadoop jar bin/test.jar ${fileBasenameNoExtension} /input /output && hdfs dfs -cat /output/*", "options": { "cwd": "${workspaceFolder}" }, "group": "build" }, { "label": "hadoop - stop service", "type": "shell", "command": "stop-all.sh", "options": { "cwd": "${workspaceFolder}" }, "group": "build" }, ] }
2. .vscode下的setting.json
{ "java.project.sourcePaths": ["src"], "java.project.outputPath": "bin", "java.project.referencedLibraries": [ "lib/**/*.jar", "/usr/local/hadoop/share/hadoop/common/hadoop-common-3.3.0.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-common-3.3.0.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.0.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.3.0.jar", "/usr/local/hadoop/share/hadoop/common/hadoop-common-3.2.4.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-common-3.2.4.jar", "/usr/local/hadoop/share/hadoop/common/lib/commons-cli-1.2.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.2.4.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.2.4.jar", "/usr/local/hadoop/share/hadoop/common/hadoop-kms-3.2.4.jar", "/usr/local/hadoop/share/hadoop/common/hadoop-nfs-3.2.4.jar", "/usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-uploader-3.2.4.jar" ] }
3. Java源码
import java.io.FileInputStream; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class CopyFromLocalFile { /** * 判断路径是否存在 */ public static boolean test(Configuration conf, String path) { try (FileSystem fs = FileSystem.get(conf)) { return fs.exists(new Path(path)); } catch (IOException e) { e.printStackTrace(); return false; } } /** * 复制文件到指定路径 若路径已存在,则进行覆盖 */ public static void copyFromLocalFile(Configuration conf, String localFilePath, String remoteFilePath) { Path localPath = new Path(localFilePath); Path remotePath = new Path(remoteFilePath); try (FileSystem fs = FileSystem.get(conf)) { /* fs.copyFromLocalFile 第一个参数表示是否删除源文件,第二个参数表示是否覆盖 */ fs.copyFromLocalFile(false, true, localPath, remotePath); } catch (IOException e) { e.printStackTrace(); } } /** * 追加文件内容 */ public static void appendToFile(Configuration conf, String localFilePath, String remoteFilePath) { Path remotePath = new Path(remoteFilePath); try (FileSystem fs = FileSystem.get(conf); FileInputStream in = new FileInputStream(localFilePath);) { FSDataOutputStream out = fs.append(remotePath); byte[] data = new byte[1024]; int read = -1; while ((read = in.read(data)) > 0) { out.write(data, 0, read); } out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 主函数 */ public static void main(String[] args) { Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://localhost:9000"); String localFilePath = "/usr/local/hadoop/text.txt"; // 本地路径 String remoteFilePath = "/user/hadoop/file/text.txt"; // HDFS路径 // String choice = "append"; // 若文件存在则追加到文件末尾 String choice = "overwrite"; // 若文件存在则覆盖 try { /* 判断文件是否存在 */ boolean fileExists = false; if (CopyFromLocalFile.test(conf, remoteFilePath)) { fileExists = true; System.out.println(remoteFilePath + " 已存在."); } else { System.out.println(remoteFilePath + " 不存在."); } /* 进行处理 */ if (!fileExists) { // 文件不存在,则上传 CopyFromLocalFile.copyFromLocalFile(conf, localFilePath, remoteFilePath); System.out.println(localFilePath + " 已上传至 " + remoteFilePath); } else if (choice.equals("overwrite")) { // 选择覆盖 CopyFromLocalFile.copyFromLocalFile(conf, localFilePath, remoteFilePath); System.out.println(localFilePath + " 已覆盖 " + remoteFilePath); } else if (choice.equals("append")) { // 选择追加 CopyFromLocalFile.appendToFile(conf, localFilePath, remoteFilePath); System.out.println(localFilePath + " 已追加至 " + remoteFilePath); } } catch (Exception e) { e.printStackTrace(); } } }
问题解答
1. 是否和WSL有关?
无关。这个错误是Java类加载失败的典型问题,和WSL环境本身没有关系——不管是Linux原生系统还是WSL,缺少依赖库都会触发该报错。
2. 为什么添加了库还报错?
- 版本冲突:你的
setting.json同时引用了Hadoop 3.3.0和3.2.4的jar包,版本混乱会导致类加载逻辑异常。 - 缺失关键依赖:
com.ctc.wstx.io.InputBootstrapper来自woodstox-corejar包,它是Hadoop解析XML配置的核心依赖,当前引用库列表里没有包含这个jar。 - 运行时类路径不完整:你直接用
java -cp命令运行时,指定的classpath只有临时jar包,没有包含Hadoop完整依赖链;而tasks.json里的hadoop - build & run任务用的是hadoop jar命令,该命令会自动加载Hadoop所有依赖,两者运行逻辑不一致。
3. 解决步骤
步骤1:清理版本冲突的依赖
打开.vscode/setting.json,删除所有3.2.4版本的Hadoop jar包,只保留和你实际安装的Hadoop版本一致的jar(先通过hadoop version确认本地Hadoop版本,再保留对应版本的依赖)。
步骤2:添加缺失的依赖jar
在setting.json的java.project.referencedLibraries中添加woodstox-core和stax-api jar包,它们位于Hadoop的common/lib目录下:
"/usr/local/hadoop/share/hadoop/common/lib/woodstox-core-*.jar", "/usr/local/hadoop/share/hadoop/common/lib/stax-api-*.jar"
(*号匹配具体版本号,也可以直接写完整文件名,比如woodstox-core-6.2.7.jar,以你Hadoop目录中的实际文件为准)
步骤3:正确运行程序
不要直接用java -cp命令运行,而是使用VSCode的任务功能:
- 打开
CopyFromLocalFile.java文件 - 按
Ctrl+Shift+B(Windows/Linux)或Cmd+Shift+B(Mac) - 选择
hadoop - build & run任务执行
如果手动运行,使用hadoop jar命令(自动加载Hadoop所有依赖):
hadoop jar bin/test.jar CopyFromLocalFile
步骤4:检查本地文件路径
确保本地文件/usr/local/hadoop/text.txt存在,否则程序会抛出文件找不到的异常。
内容的提问来源于stack exchange,提问作者liuuuuuu
相关产品推荐
相关产品推荐

