为什么关闭输入流也会关闭关联的文件描述符,即使文件描述符在多个流之间共享?
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
在流 is
和 is1
之间共享。 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 / 本机级别创建了两个独立的文件句柄,因此它们可以独立关闭。
我刚刚经历了 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
在流 is
和 is1
之间共享。 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 / 本机级别创建了两个独立的文件句柄,因此它们可以独立关闭。