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 下安装:

  1. Eclipse  Photon Release (4.8.0)
  2. JDK 1.8
  3. 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的过程大致如下:

  1. 新建一个Java Project
  2. 贴上上面的源代码
  3. 在HDFS集群上将 ./hadoop/share/hadoop 目录下相关的jar库拷出来,添加到Project依赖库中。
  4. 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程序版本不一致导致的。我这边就暂时不作深究了。。

 

 

原文地址:https://www.cnblogs.com/chorm590/p/10252752.html