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;