-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
8, 11, 17, 18, 19, 20
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
OS X arm64
$ openjdk version "18.0.2" 2022-07-19
OpenJDK Runtime Environment Homebrew (build 18.0.2+0)
OpenJDK 64-Bit Server VM Homebrew (build 18.0.2+0, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In certain situations, FileOutputStream.close() re-entrantly (i.e., recursively) invokes itself.
This behavior is horrible as it creates havoc for any sub-classes of FileOutputStream that override close() in order to perform any work at that point in lifecycle of the stream. At the very least, it's undocumented.
I have verified this bug occurs in: JDK 1.8.0_312, JDK 11.0.16, and JDK 18.0.2.
This bug occurs in JDK 8 It does occur in JDK 11, JDK 18.0.2, and presumably all versions in between.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test program below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at ReentrantClose.main(ReentrantClose.java:19)
ACTUAL -
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at ReentrantClose.main(ReentrantClose.java:19)
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at java.base/sun.nio.ch.FileChannelImpl.implCloseChannel(FileChannelImpl.java:202)
at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:112)
at java.base/java.io.FileOutputStream.close(FileOutputStream.java:387)
at ReentrantClose.close(ReentrantClose.java:13)
at ReentrantClose.main(ReentrantClose.java:19)
---------- BEGIN SOURCE ----------
import java.io.*;
public class ReentrantClose extends FileOutputStream {
public ReentrantClose(String filename) throws FileNotFoundException {
super(filename);
}
@Override
public void close() throws IOException {
new Throwable("close() invoked here").printStackTrace(System.out);
super.close();
}
public static void main(String[] args) throws Exception {
try (ReentrantClose out = new ReentrantClose("testfile")) {
out.getChannel().force(false); // this line triggers re-entrant invocation of close()
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None known.
FREQUENCY : always
OS X arm64
$ openjdk version "18.0.2" 2022-07-19
OpenJDK Runtime Environment Homebrew (build 18.0.2+0)
OpenJDK 64-Bit Server VM Homebrew (build 18.0.2+0, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
In certain situations, FileOutputStream.close() re-entrantly (i.e., recursively) invokes itself.
This behavior is horrible as it creates havoc for any sub-classes of FileOutputStream that override close() in order to perform any work at that point in lifecycle of the stream. At the very least, it's undocumented.
I have verified this bug occurs in: JDK 1.8.0_312, JDK 11.0.16, and JDK 18.0.2.
This bug occurs in JDK 8 It does occur in JDK 11, JDK 18.0.2, and presumably all versions in between.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test program below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at ReentrantClose.main(ReentrantClose.java:19)
ACTUAL -
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at ReentrantClose.main(ReentrantClose.java:19)
java.lang.Throwable: close() invoked here
at ReentrantClose.close(ReentrantClose.java:12)
at java.base/sun.nio.ch.FileChannelImpl.implCloseChannel(FileChannelImpl.java:202)
at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.close(AbstractInterruptibleChannel.java:112)
at java.base/java.io.FileOutputStream.close(FileOutputStream.java:387)
at ReentrantClose.close(ReentrantClose.java:13)
at ReentrantClose.main(ReentrantClose.java:19)
---------- BEGIN SOURCE ----------
import java.io.*;
public class ReentrantClose extends FileOutputStream {
public ReentrantClose(String filename) throws FileNotFoundException {
super(filename);
}
@Override
public void close() throws IOException {
new Throwable("close() invoked here").printStackTrace(System.out);
super.close();
}
public static void main(String[] args) throws Exception {
try (ReentrantClose out = new ReentrantClose("testfile")) {
out.getChannel().force(false); // this line triggers re-entrant invocation of close()
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None known.
FREQUENCY : always
- relates to
-
JDK-8305748 Clarify reentrant behavior of close() in FileInputStream, FileOutputStream, and RandomAccessFile
-
- Resolved
-