Eclipse maven hadoop -- java.io.IOException: No FileSystem for scheme: hdfs
2019-01-10
概述
今天在Windows系统下新安装了Eclipse和maven的环境,想利用Maven构建一个Hadoop程序的,结果却发现程序运行时一直报 “No FileSystem for scheme: hdfs” 的异常。网友贴出的解决方案在我这都不适用。经过数小时痛苦的折磨以后才终于找到我这种情况的原因:Maven自动下载的 hadoop-hdfs-2.7.7.jar 库文件不正确!!!
环境
HDFS搭建在一组ubuntu server集群上,系统正常运行。 Hadoop 2.7.7
Windows 10 下安装:
- Eclipse Photon Release (4.8.0)
- JDK 1.8
- Maven 3.6.0
Eclipse上所使用的主要源码如下:
1 void access() { 2 Configuration conf = new Configuration(); 3 conf.set("fs.defaultFS", "hdfs://usmaster:8020"); 4 try { 5 FileSystem fs = FileSystem.get(conf); //运行到该行时报异常。 6 System.out.println(fs.getHomeDirectory().toUri().toString()); 7 System.out.println("read end!"); 8 } catch (Exception e) { 9 e.printStackTrace(); 10 } 11 }
异常栈信息如下:
java.io.IOException: No FileSystem for scheme: hdfs at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2658) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2665) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:93) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2701) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2683) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:372) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:171) ...
解决过程
遇到这个问题,首先思考下异常原因:No FileSystem for scheme: hdfs 。似乎是不能识别hdfs协议!那首先来检查一下HDFS系统的运行状况。经检查,我的HDFS集群运行正常。WEB UI正常打开,也可以通过Shell命令正常地与HDFS交互。排除掉HDFS系统的原因。
其次检查我的源代码,为了纠错将源代码缩减到最减化的地步,如上面贴出来的代码所示。根据代码来看,也可以排除掉我写的代码有错误的原因。
然后再检查Maven的pom配置信息。我的pom.xml全文如下所示:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>com.chorm</groupId> 6 <artifactId>HelloWorld</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>jar</packaging> 9 10 <name>HDFS</name> 11 <url>http://maven.apache.org</url> 12 13 <properties> 14 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 15 <hadoop.version>2.7.7</hadoop.version> 16 </properties> 17 18 <dependencies> 19 <dependency> 20 <groupId>junit</groupId> 21 <artifactId>junit</artifactId> 22 <version>3.8.1</version> 23 <scope>test</scope> 24 </dependency> 25 26 <dependency> 27 <groupId>org.apache.hadoop</groupId> 28 <artifactId>hadoop-client</artifactId> 29 <version>${hadoop.version}</version> 30 </dependency> 31 32 </dependencies> 33 </project>
同时检查了项目的Maven Dependencies,该有的jar包都有。似乎也和Maven依赖没关系。
那接下来再检查JRE,似乎也没发现问题。。。
好嘛,检查一圈下来哪哪都没问题,那它怎么就是报错???
现在只剩百度了。。。经过一番搜索,网上虽然也有不少报相同异常的情况,但是按照他们的方案都没能解决我的问题。还得继续靠自己来分析。。。
那我就不用Maven来构建程序。我直接创建一个Java Project,看看有没有可能是我下载的Maven程序有问题。创建Java Project的过程大致如下:
- 新建一个Java Project
- 贴上上面的源代码
- 在HDFS集群上将 ./hadoop/share/hadoop 目录下相关的jar库拷出来,添加到Project依赖库中。
- run it...
正常运行。。。
这似乎真和Maven脱不了干系。
那只能调试程序了。。。。
首先定位到抛出这个异常的代码:
at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2658)
图1
由上图来看,抛异常是因为claszz变量在第2652行和第2655行都没能得到对象引起的(找不到对象的变量真的是可怕)。第2652行是要从Configuration对象中读取配置信息的,就是从core-default.xml或core-site.xml中读取配置信息。这个信息我这边并没有指定,所以它肯定是返回一个NULL的。那我们在第2654行打一个断点,来调试一下看怎么回事。
图2
单步跳过第2655行以后看一下这个SERVICE_FILE_SYSTEMS变量。
图3
似乎这个对象里真的没有key值能匹配“hdfs”的对象值啊。这就有点奇怪了。那再调试一下前面自己建的那个“Java Project”,在同样位置打断点来查看这个变量值。
图4
神奇了。。。为什么用maven构建的程序会导致这个SERVICE_FILE_SYSTEMS变量里没有“hdfs”的对象?去看看这个SERVICE_FILE_SYSTEMS是在哪里赋值的。
图5
查了源码,这个SERVICE_FILE_SYSTEMS只在这一处地方有赋值操作。其值来自于ServiceLoader.load(FileSystem.class)。我不了解这个ServiceLoader.load()方法是干什么的,不过似乎和hadoop的FileSystem有关系,经查询这个FileSystem来自于hadoop-common-2.7.7.jar库。这个FileSystem类在Maven构建的程序中的依赖库中能找到,在Java Project中手动添加的依赖库中也能找到。
图6
再去查一下上图4中那个与“hdfs”有关的DistriubtedFileSystem的类。却发现只能在自己创建的Java Project中找到它位于hadoop-hdfs-2.7.7.jar中,在Maven构建的程序中没有!!难道是maven自动下载的hadoop-hdfs-2.7.7.jar 库有问题?打开来看一下。
图7
神奇有没有,maven自动下载的库中也有这个class。但是为什么似乎Eclipse就是识别不到它??
再对比一下这两个hadoop-hdfs-2.7.7.jar的文件属性信息。
图8
文件大小显然不一样,这两个库有差异啊!
那将我手动从HDFS中导出来的hadoop-hdfs-2.7.7.jar替换掉我Maven自动下载的那个hadoop-hdfs-2.7.7.jar来试试。
图9
运行程序。。
图10
问题解决!!!!
不过我至今搞不懂为什么maven自动下载的那个hadoop-hdfs-2.7.7.jar库会不行。。也搞不懂这两个库之间的差异是怎么回事。
不过我这边安装的HDFS是直接在Hadoop的官网上下载的2.7.7版本。我不知道Maven帮我下载的库是不是什么CDH版本的。也许真的是依赖库文件来源的Hadoop程序版本不一致导致的。我这边就暂时不作深究了。。