JDK-4099999 : File{Input,Output}Stream finalizer should not close FileDescriptor
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.1.4,1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt,windows_2000
  • CPU: x86
  • Submitted: 1997-12-17
  • Updated: 2007-02-27
  • Resolved: 2007-02-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
Name: rm29839			Date: 12/17/97


finalize() method of the FileInputStream and
the FileOutputStream calls close() method,
which closes the FileDescriptor of the
FileInput/OutputStream.
This is good while one FileDescriptor is used
by exactly one FileInput/OutputStream.
If, for example, I open an RandomAccessFile,
get the FileDescriptor, create the
FileInputStream, use FileInputStream and clear
the reference to it, then, when the
FileInputStream will be finalized,
the RandomAccessFile will be inaccessible.
Here the source:

import java.io.*;

public class IOTest extends FileOutputStream
  {

  IOTest(FileDescriptor fd)
    { super(fd); }

  public void close()
    throws IOException
    {
    super.close();
    System.out.println("The file stream is closed");
    }

  protected void finalize()
    throws IOException
    {
    super.finalize();
    System.out.println("The file stream is finalized");
    }

  public static void main(String[] args)
    throws Exception
    {
    RandomAccessFile f = new RandomAccessFile("f", "rw");
    IOTest iot = new IOTest(f.getFD());
    // Do anything with iot, but don't call iot.close() explicitly.
    iot = null;
    // This way to cause finalization seems complicated,
    // but System.runFinalization() don't finalize iot.
    try {
      byte[][] b = new byte[100][];
      for (int i = 0; i < b.length; i++)
        { b[i] = new byte[10000000]; }
      }
    catch (OutOfMemoryError e) {
      }
    f.writeUTF("The string");
    f.close();
    }

  }

Here the output of the program:

The file stream is closed
The file stream is finalized
java.io.IOException: write error
        at java.io.RandomAccessFile.writeUTF(RandomAccessFile.java:842)
        at IOTest.main(IOTest.java:39)

So, f.writeUTF("The string") throws IOException.

As I think, FileInput/OutputStream should not
have finalize() method, because this classes
don't use system resources themself. Instead,
finalize() method should be placed in the class
FileDescriptor.
(Review ID: 22026)
======================================================================

Comments
EVALUATION The problem of recyling of File Descriptors will be addressed by a fix to: 6322678 targetted for Dolphin.
18-04-2006

EVALUATION I agree with the submitter that the FileInputStream and FileOutputStream classes should not have finalize methods that close the stream. Unfortunately, these methods have always done this. Since existing programs may rely upon this behavior, removing these methods would break compabitility. There is a simple workaround for this problem. -- mr@eng 1/7/1998 Actually, this problem can be fixed by arranging for each FileDescriptor to keep references to all streams that were created from it. That way none of the streams will become finalizable until the file descriptor itself is finalizable, which will only happen once all of the streams become finalizable. -- mr@eng 2/27/1998 The overhead of implementing this fix seems too high, given that there is a straightforward workaround. I'm lowering the priority of this bug to 4 for now. -- mr@eng 8/25/1998
27-02-1998

WORK AROUND Create a subclass of FileOutputStream (or FileInputStream, as appropriate) that overrides the finalize method with a method that does not close the stream. -- mr@eng 1/7/1998
07-01-1998