United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-5005419 : Repeated close() of Writers with nio charsets fails in 1.4.2 and tiger

Details
Type:
Bug
Submit Date:
2004-03-01
Status:
Closed
Updated Date:
2010-02-17
Project Name:
JDK
Resolved Date:
2005-05-28
Component:
core-libs
OS:
windows_xp
Sub-Component:
java.nio.charsets
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.2_03
Fixed Versions:
1.4.2_09 (b02)

Related Reports
Relates:

Sub Tasks

Description
There is an incompatible behavior between 1.3.1_XX and 1.4.2_0X.


The attached test program works well in 1.3.1_0X(1.4.1_0X also),
but not in 1.4.2_0X(1.5.betab38).

REPRODUCE :
 (1) Compile test.java 
 (2) Launch "java test windows-31j" in 1.3.1_11
 
     You will see only the message, "2nd close"

K:\illegal-excp>java test windows-31j
2nd close


 (3) Launch "java test windows-31j" in 1.4.2_03

     You will see the stack trace as follows.

K:\illegal-excp>java test windows-31j     
2nd close
catch in main
java.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END


        at java.nio.charset.CharsetEncoder.throwIllegalStateException(CharsetEnc
oder.java:933)
        at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:529)
        at sun.nio.cs.StreamEncoder$CharsetSE.flushLeftoverChar(StreamEncoder.ja
va:358)
        at sun.nio.cs.StreamEncoder$CharsetSE.implClose(StreamEncoder.java:414)
        at sun.nio.cs.StreamEncoder.close(StreamEncoder.java:160)
        at java.io.OutputStreamWriter.close(OutputStreamWriter.java:222)
        at java.io.PrintWriter.close(PrintWriter.java:137)
        at test.main(test.java:10)


The java.lang.IllegalStateException occurs in 1.4.2( and Tiger b38 ),
not in 1.3.1(1.4.0).


INVESTIGATION:
  
===== Test Program ( test.java ) =========
import java.io.*;
class test {
    public static void main( String arg[] ) {
	try {
	    OutputStreamWriter osw = 
		new OutputStreamWriter( new MyOutputStream("file"), arg[0] );
	    PrintWriter pw = new PrintWriter( osw );
	    pw.close();                         // 1st close 
	    System.out.println("2nd close");
	    pw.close();                         // 2nd close
	}
	catch( Exception e ) {
	    System.out.println("catch in main");
	    e.printStackTrace();
	}

    }
}

class MyOutputStream extends FileOutputStream {
    MyOutputStream( String s ) throws FileNotFoundException {
	super(s);
    }
    public void close() throws IOException {
	throw new IOException("Dummy Exception");
    }
}
==========================================

The above program is implemented as an exception appears on PrintWriter close. 
 (Please don't consider the sample code has problem.)
Please consider the above behavior of MyOutputStream simulates "some exception"
in the 3rd line of followings.
     - OutputStreamWriter object is created with char. encoding
       which is supported by nio .
     - Printwriter object is created based on OutputStreamWriter object.
     - Some exception occurs in close() for PrintWriter (pw.close() in "1st close" line)
       and close() is launched again.(pw.close() in "2nd close" line.)

Indeed, the API specifications in java.nio.charset.CharsetEncoder#encode mentions
the IllegalStateException in "Throw" section.

The users can be only aware of the OutputStreamWriter and  PrintWriter. 
However, the API docs of those classes does not mention IllegalStateException.
As a result, Java users don't write the code which can catch IllegalStateException
and will be confused because of an unexpected exception.

It means that users can not port the programs written in 1.3.1 to environment
based on 1.4.2.


PROBLEM: 

-  losing portability from 1.3.1(1.4.0) to 1.4.2 (and Tiger)

===========================================================================

                                    

Comments
EVALUATION

This bug looks essentially like a duplicate of 5005426 with similarly supplied
test case and suggested fix. 5005426 has been evaluated and fix is in progress.
What is probably required here for this bug is a statement regarding whether
the behaviour described and observed with the supplied test case is in violation
of the PrintWriter specification or not. Such a statement ought to provided in 
due course.
###@###.### 2004-04-27

I agree that this is likely a duplicate of 5005426.
There may be a further bug that repeated close() should always be a no-op,
regardless of the underlying stream.

###@###.### 2004-08-31
                                     
2004-08-31
SUGGESTED FIX

The followings are sent by the licensee.
Please evaluate.

*** org/OutputStreamWriter.java	  2 27 16:38:56 2004
--- OutputStreamWriter.java	  3  1 10:08:58 2004
***************
*** 9,14 ****
--- 9,18 ----
  
  import java.nio.charset.Charset;
  import java.nio.charset.CharsetEncoder;
+ import java.nio.charset.CoderMalfunctionError;
+ import java.nio.charset.CharacterCodingException;
+ import java.nio.charset.MalformedInputException;
+ import java.nio.charset.UnmappableCharacterException;
  import sun.nio.cs.StreamEncoder;
  
  
***************
*** 166,174 ****
--- 170,193 ----
       * be invoked by PrintStream.
       */
      void flushBuffer() throws IOException {
+ 	try {
  	    se.flushBuffer();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
  	
+     }
+ 
      /**
       * Write a single character.
       *
***************
*** 175,182 ****
--- 194,215 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void write(int c) throws IOException {
+ 	try {
  	    se.write(c);
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Write a portion of an array of characters.
***************
*** 188,195 ****
--- 221,242 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void write(char cbuf[], int off, int len) throws IOException {
+ 	try {
  	    se.write(cbuf, off, len);
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Write a portion of a string.
***************
*** 201,208 ****
--- 248,269 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void write(String str, int off, int len) throws IOException {
+ 	try {
  	    se.write(str, off, len);
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Flush the stream.
***************
*** 210,217 ****
--- 271,292 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void flush() throws IOException {
+ 	try {
  	    se.flush();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Close the stream.
***************
*** 219,225 ****
--- 294,314 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void close() throws IOException {
+ 	try {
  	    se.close();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	     throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	     throw new IOException("CoderMalfunctionError occurred. in java.nio");
+ 	}
      }
  
  }
*** org/InputStreamReader.java	  2 27 16:39:20 2004
--- InputStreamReader.java	  3  1 10:12:08 2004
***************
*** 9,14 ****
--- 9,18 ----
  
  import java.nio.charset.Charset;
  import java.nio.charset.CharsetDecoder;
+ import java.nio.charset.CoderMalfunctionError;
+ import java.nio.charset.CharacterCodingException;
+ import java.nio.charset.MalformedInputException;
+ import java.nio.charset.UnmappableCharacterException;
  import sun.nio.cs.StreamDecoder;
  
  
***************
*** 148,155 ****
--- 152,175 ----
       * @exception  IOException  If an I/O error occurs
       */
      public int read() throws IOException {
+ 	try {
  	    return sd.read();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	    throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (UnsupportedOperationException e) {
+ 	    throw new IOException("UnsupportedOperationException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	    throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Read characters into a portion of an array.
***************
*** 164,171 ****
--- 184,207 ----
       * @exception  IOException  If an I/O error occurs
       */
      public int read(char cbuf[], int offset, int length) throws IOException {
+ 	try {
  	    return sd.read(cbuf, offset, length);
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	    throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (UnsupportedOperationException e) {
+ 	    throw new IOException("UnsupportedOperationException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	    throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Tell whether this stream is ready to be read.  An InputStreamReader is
***************
*** 175,182 ****
--- 211,234 ----
       * @exception  IOException  If an I/O error occurs
       */
      public boolean ready() throws IOException {
+ 	try {
  	    return sd.ready();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	    throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (UnsupportedOperationException e) {
+ 	    throw new IOException("UnsupportedOperationException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	    throw new IOException("CoderMalfunctionError occurred. in java.nio");
  	}
+     }
  
      /**
       * Close the stream.
***************
*** 184,190 ****
--- 236,258 ----
       * @exception  IOException  If an I/O error occurs
       */
      public void close() throws IOException {
+ 	try {
  	    sd.close();
+ 	} catch (IllegalStateException e) {
+ 	    throw new IOException("IllegalStateException occurred. in java.nio");
+ 	} catch (IllegalArgumentException e) {
+ 	    throw new IOException("IllegalArgumentException occurred. in java.nio");
+ 	} catch (MalformedInputException e) {
+ 	    throw new IOException("MalformedInputException occurred. in java.nio");
+ 	} catch (UnmappableCharacterException e) {
+ 	    throw new IOException("UnmappableCharacterException occurred. in java.nio");
+ 	} catch (CharacterCodingException e) {
+ 	    throw new IOException("CharacterCodingException occurred. in java.nio");
+ 	} catch (UnsupportedOperationException e) {
+ 	    throw new IOException("UnsupportedOperationException occurred. in java.nio");
+ 	} catch (CoderMalfunctionError e) {
+ 	    throw new IOException("CoderMalfunctionError occurred. in java.nio");
+ 	}
      }
  
  }


###@###.### 2004-03-01

===========================================================================
                                     
2004-03-01



Hardware and Software, Engineered to Work Together