Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8305752

Clarify reentrant behavior of close() in FileInputStream, FileOutputStream, and RandomAccessFile

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 21
    • core-libs
    • minimal
    • This is a documentation-only change.
    • Java API
    • SE

      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

            acobbs Archie Cobbs
            acobbs Archie Cobbs
            Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: