为什么关闭输入流也会关闭关联的文件描述符,即使文件描述符在多个流之间共享?

Why closing an Input Stream closes the associated File Descriptor as well, even the File Descriptor is shared among multiple streams ?

我刚刚经历了 FileInputStream 的实现,并与关闭方法实现混淆,如下所示,

public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }
        if (channel != null) {
           channel.close();
        }

        fd.closeAll(new Closeable() {
            public void More ...close() throws IOException {
               close0();
           }
        });
}

这会在 FileDescriptor 上内部调用 closeAll,这会释放所有 Closables(不仅是调用关闭的特定实例)。因此,对输入流的关闭调用将关闭所有共享该 FileDescriptor 的流。

    FileInputStream is = new FileInputStream("Some file");
    BufferedInputStream br = new BufferedInputStream(is);

    FileDescriptor fd = is.getFD();

    FileInputStream is1 = new FileInputStream(fd);
    BufferedInputStream br1 = new BufferedInputStream(is1);

    is.close();
    System.out.println(is1.read());

在上面的示例中,FileDescriptor fd 在流 isis1 之间共享。 is 的关闭调用也会关闭 is1(基本上 fd 是 closed/released)

我的问题是,FileInputStream 有一个标志来指示它是否关闭,但仍然为什么它在其他活动流指向它时关闭 FileDescriptor,使它们全部 fail/invalid,而不是仅仅关闭调用实例并在没有其他流指向它时关闭 FileDescriptor?

如果您从 File 对象而不是 FileDescriptor 打开 FileInputStreams,您将获得预期的行为:

File f = new File( ... );
InputStream in1 = new FileInputStream( f );
InputStream in2 = new FileInputStream( f );

您将在 FileInputStream( File ) constructor source that this creates a new FileDescriptor for each FileInputStream instead of sharing one passed in, as happens in the FileInputStream( FileDescriptor ) 构造函数中看到。

javadoc 开始,FileDescriptor 包装了代表打开文件句柄的底层原生 OS 结构。

InputStream.close() 的全部目的是清理那些本机资源。因此,如果两个 InputStreams 共享本机文件句柄,当一个关闭时,另一个也会受到影响。

在我上面提供的替代示例中,在 OS / 本机级别创建了两个独立的文件句柄,因此它们可以独立关闭。