Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2195035 | 6u25 | Kevin Walls | P3 | Closed | Fixed | b01 |
Windows XP
FULL JDK VERSION
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode)
DESCRIPTION
The problem relates to the use of the api constructor method
FileInputStream(FileDescriptor), in combination with the class's getFD()
method and its finalizer method. The constructor creates a new
FileInputStream Object based on an existing FileDescriptor Object.
By first creating a FileInputStream using a different constructor,
and then calling getFD(), the FileInputStream(FileDescriptor)
constructor can be used to create another FileInputStream.
This means we have two FileInputStreams using the same FileDescriptor class,
and so the same native fd. If one of these objects hten becomes eligible for
gc, the finalizer can run, which will close the native fd, even though
the other FileInputStream object is still using it.
A testcase that reproduces this problem is specified below:
==============
import java.io.*;
public class FIS {
public static void main(String[] args) {
try {
/*Create initial FIS for file */
FileInputStream fis1 = new FileInputStream("thefile.txt");
/* Get the FileDescriptor from the fis */
FileDescriptor fd = fis1.getFD();
/* Create a new FIS based on the existing FD (so the two FIS's share the same native fd) */
FileInputStream fis2 = new FileInputStream(fd);
/* allow fis1 to be gc'ed */
fis1 = null;
int ret = 0;
while(ret >= 0) {
/* encourage gc */
System.gc();
/* read from fis2 - when fis1 is gc'ed and finalizer is run, read will fail */
System.out.println("about to read");
ret = fis2.read();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
===============
This would be a problem whenever a FileDescripter from any existing Stream
is passed into a FileInputStream or in fact to any Stream which has a
constructor that takes a FileDescriptor and has a finalizer that closes
the fd (i.e. FileOutputStream would have the same problem.)
This looks like an api issue.
The finalizer seems a sensible thing to have, so that if we forget to close
the FileInputStream, it (and the native fd) are closed at some point.
However, this logic requires that a native fd is uniquely associated with
a single stream, but this is not guaranteed when you can create a FileInputStream
based on an existing FileDescriptor object(and so existing native fd).
- backported by
-
JDK-2195035 FileInputStream(FileDescriptor) throws IOException when reading a file if FD is invalid
-
- Closed
-
- duplicates
-
JDK-6494786 client VM throws IOException while running Solaris Web Start Wizards SDK car utility
-
- Closed
-
-
JDK-4099999 File{Input,Output}Stream finalizer should not close FileDescriptor
-
- Closed
-
- relates to
-
JDK-6524062 api/java_io/FileInputStream/index.html#Finalize[Finalize0001] fails on JDK 7 since b06
-
- Closed
-
-
JDK-7082769 FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor be closed when still in use
-
- Closed
-
-
JDK-6568138 FileDescriptors can sometimes escape being closed by the finalizer
-
- Closed
-