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);
}
}
+ }
}