Summary
Document the reentrant behavior of the close()
method in FileInputStream
, FileOutputStream
, and RandomAccessFile
.
Problem
FileInputStream
, FileOutputStream
, and RandomAccessFile
can have an assocated FileChannel
.
When close()
is invoked on one of these classes, it in turn invokes close()
on the associated channel (if any). But when the associated channel's close()
method is invoked, it in turn invokes close()
on the associated stream (if any).
As a result, these I/O stream close()
methods invoke themselves reentrantly when there is an associated channel.
This is not a problem for these classes because they are written to handle this (i.e., they are idempotent), but it can be surprising (or worse, just silently bug-inducing) for subclasses that override these close()
methods.
Solution
The Javadoc for these close()
methods should have a note/warning about this reentrant behavior for the benefit of subclass implementors.
Specification
Update Javadoc as follows:
diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java
index e882946cf74..e32518d0ea7 100644
--- a/src/java.base/share/classes/java/io/FileInputStream.java
+++ b/src/java.base/share/classes/java/io/FileInputStream.java
@@ -499,6 +499,11 @@ public class FileInputStream extends InputStream
* If cleanup of native resources is needed, other mechanisms such as
* {@linkplain java.lang.ref.Cleaner} should be used.
*
+ * <p>
+ * If this stream has an associated channel then this method will close the
+ * channel, which in turn will close this stream. Subclasses that override
+ * this method should be prepared to handle possible reentrant invocation.
+ *
* @throws IOException {@inheritDoc}
*
* @revised 1.4
diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java
index 5d2dead569a..c985c2d6363 100644
--- a/src/java.base/share/classes/java/io/FileOutputStream.java
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java
@@ -392,6 +392,11 @@ public class FileOutputStream extends OutputStream
* If cleanup of native resources is needed, other mechanisms such as
* {@linkplain java.lang.ref.Cleaner} should be used.
*
+ * <p>
+ * If this stream has an associated channel then this method will close the
+ * channel, which in turn will close this stream. Subclasses that override
+ * this method should be prepared to handle possible reentrant invocation.
+ *
* @throws IOException if an I/O error occurs.
*
* @revised 1.4
diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java
index 71f9956b15b..57f984ad9c4 100644
--- a/src/java.base/share/classes/java/io/RandomAccessFile.java
+++ b/src/java.base/share/classes/java/io/RandomAccessFile.java
@@ -697,6 +697,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* <p> If this file has an associated channel then the channel is closed
* as well.
*
+ * @apiNote
+ * If this stream has an associated channel then this method will close the
+ * channel, which in turn will close this stream. Subclasses that override
+ * this method should be prepared to handle possible reentrant invocation.
+ *
* @throws IOException if an I/O error occurs.
*
* @revised 1.4
diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java
index 741ad048cb7..4657905e963 100644
--- a/src/java.base/share/classes/java/nio/channels/FileChannel.java
+++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java
@@ -122,7 +122,8 @@ import jdk.internal.javac.PreviewFeature;
* the originating object, and vice versa. Changing the file's length via the
* file channel will change the length seen via the originating object, and vice
* versa. Changing the file's content by writing bytes will change the content
- * seen by the originating object, and vice versa.
+ * seen by the originating object, and vice versa. Closing the channel will
+ * close the originating object.
*
* <a id="open-mode"></a> <p> At various points this class specifies that an
* instance that is "open for reading," "open for writing," or "open for
- csr of
-
JDK-8305748 Clarify reentrant behavior of close() in FileInputStream, FileOutputStream, and RandomAccessFile
-
- Resolved
-