src/share/classes/java/io/FileInputStream.java

Print this page

        

*** 54,63 **** --- 54,73 ---- private FileChannel channel = null; private final Object closeLock = new Object(); private volatile boolean closed = false; + private static final ThreadLocal<Boolean> runningFinalize = + new ThreadLocal<>(); + + private static boolean isRunningFinalize() { + Boolean val; + if ((val = runningFinalize.get()) != null) + return val.booleanValue(); + return false; + } + /** * Creates a <code>FileInputStream</code> by * opening a connection to an actual file, * the file named by the path name <code>name</code> * in the file system. A new <code>FileDescriptor</code>
*** 122,132 **** } if (name == null) { throw new NullPointerException(); } fd = new FileDescriptor(); ! fd.attach(this); open(name); } /** * Creates a <code>FileInputStream</code> by using the file descriptor --- 132,142 ---- } if (name == null) { throw new NullPointerException(); } fd = new FileDescriptor(); ! fd.incrementAndGetUseCount(); open(name); } /** * Creates a <code>FileInputStream</code> by using the file descriptor
*** 162,174 **** } fd = fdObj; /* * FileDescriptor is being shared by streams. ! * Register this stream with FileDescriptor tracker. */ ! fd.attach(this); } /** * Opens the specified file for reading. * @param name the name of the file --- 172,185 ---- } fd = fdObj; /* * FileDescriptor is being shared by streams. ! * Ensure that it's GC'ed only when all the streams/channels are done ! * using it. */ ! fd.incrementAndGetUseCount(); } /** * Opens the specified file for reading. * @param name the name of the file
*** 291,307 **** return; } closed = true; } if (channel != null) { channel.close(); } ! fd.closeAll(new Closeable() { ! public void close() throws IOException { close0(); } - }); } /** * Returns the <code>FileDescriptor</code> * object that represents the connection to --- 302,332 ---- return; } closed = true; } if (channel != null) { + /* + * Decrement the FD use count associated with the channel + * The use count is incremented whenever a new channel + * is obtained from this stream. + */ + fd.decrementAndGetUseCount(); channel.close(); } ! ! /* ! * Decrement the FD use count associated with this stream ! */ ! int useCount = fd.decrementAndGetUseCount(); ! ! /* ! * If FileDescriptor is still in use by another stream, the finalizer ! * will not close it. ! */ ! if ((useCount <= 0) || !isRunningFinalize()) { close0(); } } /** * Returns the <code>FileDescriptor</code> * object that represents the connection to
*** 311,323 **** * @return the file descriptor object associated with this stream. * @exception IOException if an I/O error occurs. * @see java.io.FileDescriptor */ public final FileDescriptor getFD() throws IOException { ! if (fd != null) { ! return fd; ! } throw new IOException(); } /** * Returns the unique {@link java.nio.channels.FileChannel FileChannel} --- 336,346 ---- * @return the file descriptor object associated with this stream. * @exception IOException if an I/O error occurs. * @see java.io.FileDescriptor */ public final FileDescriptor getFD() throws IOException { ! if (fd != null) return fd; throw new IOException(); } /** * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
*** 337,346 **** --- 360,376 ---- */ public FileChannel getChannel() { synchronized (this) { if (channel == null) { channel = FileChannelImpl.open(fd, true, false, this); + + /* + * Increment fd's use count. Invoking the channel's close() + * method will result in decrementing the use count set for + * the channel. + */ + fd.incrementAndGetUseCount(); } return channel; } }
*** 359,372 **** * @exception IOException if an I/O error occurs. * @see java.io.FileInputStream#close() */ protected void finalize() throws IOException { if ((fd != null) && (fd != FileDescriptor.in)) { ! /* if fd is shared, the references in FileDescriptor ! * will ensure that finalizer is only called when ! * safe to do so. All references using the fd have ! * become unreachable. We can call close() */ close(); } } } --- 389,408 ---- * @exception IOException if an I/O error occurs. * @see java.io.FileInputStream#close() */ protected void finalize() throws IOException { if ((fd != null) && (fd != FileDescriptor.in)) { ! ! /* ! * Finalizer should not release the FileDescriptor if another ! * stream is still using it. If the user directly invokes ! * close() then the FileDescriptor is also released. */ + runningFinalize.set(Boolean.TRUE); + try { close(); + } finally { + runningFinalize.set(Boolean.FALSE); } } + } }