在执行BufferedReader.close()时Hadoop FileSystem关闭了异常

时间:2013-11-18 21:05:17

标签: java hadoop mapreduce hdfs

在Reduce设置方法中,我尝试关闭BufferedReader对象并获得FileSystem已关闭的异常。它不会一直发生。这是我用来创建BufferedReader

的代码段
    String fileName = <some HDFS file path>
    Configuration conf = new Configuration();
    FileSystem fs = FileSystem.get(conf);
    Path hdfsPath = new Path(filename);
    FSDataInputStream in = fs.open(hdfsPath);
    InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

我从bufferedReader读取内容,一旦完成所有读取,我就关闭它。

这是读取它的代码

String line;
while ((line = reader.readLine()) != null) {
    // Do something
}

这段关闭读者的代码。

    if (bufferedReader != null) {
        bufferedReader.close();
    }

这是我执行bufferedReader.close()时发生的异常的堆栈跟踪。

  

I,[2013-11-18T04:56:51.601135#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:565)

     

I,[2013-11-18T04:56:51.601168#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   org.apache.hadoop.hdfs.DFSInputStream.close(DFSInputStream.java:522)

     

I,[2013-11-18T04:56:51.601199#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   java.io.FilterInputStream.close(FilterInputStream.java:155)

     

I,[2013-11-18T04:56:51.601230#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   sun.nio.cs.StreamDecoder.implClose(StreamDecoder.java:358)

     

I,[2013-11-18T04:56:51.601263#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   sun.nio.cs.StreamDecoder.close(StreamDecoder.java:173)

     

I,[2013-11-18T04:56:51.601356#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   java.io.InputStreamReader.close(InputStreamReader.java:182)

     

I,[2013-11-18T04:56:51.601395#25683]信息 - :   attempt_201310111840_142285_r_000009_0:at   java.io.BufferedReader.close(BufferedReader.java:497)

我不确定为什么会发生这种异常。这不是多线程的,因此,我不认为会出现任何形式的竞争条件。能帮助我理解吗。

谢谢,

Venk

2 个答案:

答案 0 :(得分:32)

hadoop文件系统API有一个鲜为人知的问题:FileSystem.get为每个具有相同文件系统的调用返回相同的对象。因此,如果一个人在任何地方关闭,他们都会关闭。你可以辩论这个决定的优点,但这就是它的方式。

因此,如果您尝试关闭BufferedReader,并尝试清除缓冲的某些数据,但基础流连接到已关闭的FileSystem,您将收到此错误。检查代码中是否有关闭FileSystem对象的其他位置,并查找竞争条件。另外,我相信Hadoop本身会在某些时候关闭FileSystem,所以为了安全起见,你应该只能从Reducer的setup,reduce或cleanup方法中访问它(或者配置,减少和关闭,具体取决于哪个API)你正在使用。)

答案 1 :(得分:16)

您必须使用FileSystem.newInstance来避免使用共享连接(如Joe K所述)。它将为您提供一个独特的非共享实例。