src/java.base/share/classes/java/io/FileInputStream.java
Print this page
rev 11078 : 8025619: (fc) FileInputStream.getChannel on closed stream returns FileChannel that doesn't know that stream is closed
Summary: If the stream is closed ensure getChannel() returns a closed channel. Also, FileKey.create() should throw an IOException directly instead of wrapping it in an Error.
Reviewed-by: TBD
rev 11079 : 8025619.01
rev 11080 : 8025619.02
rev 11081 : 8025619.03
*** 24,33 ****
--- 24,34 ----
*/
package java.io;
import java.nio.channels.FileChannel;
+ import java.util.concurrent.atomic.AtomicBoolean;
import sun.nio.ch.FileChannelImpl;
/**
* A <code>FileInputStream</code> obtains input bytes
*** 55,68 ****
* The path of the referenced file
* (null if the stream is created with a file descriptor)
*/
private final String path;
! private FileChannel channel = null;
! private final Object closeLock = new Object();
! private volatile boolean closed = false;
/**
* Creates a <code>FileInputStream</code> by
* opening a connection to an actual file,
* the file named by the path name <code>name</code>
--- 56,68 ----
* The path of the referenced file
* (null if the stream is created with a file descriptor)
*/
private final String path;
! private volatile FileChannel channel;
! private final AtomicBoolean closed = new AtomicBoolean(false);
/**
* Creates a <code>FileInputStream</code> by
* opening a connection to an actual file,
* the file named by the path name <code>name</code>
*** 311,328 ****
*
* @revised 1.4
* @spec JSR-51
*/
public void close() throws IOException {
! synchronized (closeLock) {
! if (closed) {
return;
}
! closed = true;
! }
! if (channel != null) {
! channel.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
--- 311,328 ----
*
* @revised 1.4
* @spec JSR-51
*/
public void close() throws IOException {
! if (!closed.compareAndSet(false, true)) {
! // if compareAndSet() returns false closed was already true
return;
}
!
! FileChannel fc = channel;
! if (fc != null) {
! fc.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
close0();
*** 362,377 ****
*
* @since 1.4
* @spec JSR-51
*/
public FileChannel getChannel() {
synchronized (this) {
! if (channel == null) {
! channel = FileChannelImpl.open(fd, path, true, false, this);
}
- return channel;
}
}
private static native void initIDs();
private native void close0() throws IOException;
--- 362,388 ----
*
* @since 1.4
* @spec JSR-51
*/
public FileChannel getChannel() {
+ FileChannel fc = this.channel;
+ if (fc == null) {
synchronized (this) {
! fc = this.channel;
! if (fc == null) {
! this.channel = fc = FileChannelImpl.open(fd, path, true, false, this);
! if (closed.get()) {
! try {
! fc.close();
! } catch (IOException ioe) {
! throw new InternalError(ioe); // should not happen
! }
! }
! }
}
}
+ return fc;
}
private static native void initIDs();
private native void close0() throws IOException;