Name: bsC130419 Date: 07/25/2001
java version "1.4.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b65)
Java HotSpot(TM) Client VM (build 1.4.0-beta-b65, mixed mode)
The following test program sends a string to the echo server and retrieves it
back. It is only a slight extension of the echo demo found in the online
documentation. This program works properly under the Java 2 jdk 1.3 but causes
a stack overflow under 1.4 beta.
Here is the main program:
package princeton.com.x;
import java.io.IOException;
import princeton.com.x.TestSocket;
public class TestSocketApp
{
public static void main(String[] args) throws IOException
{
// create a new socket and connect to the echo server
TestSocket socket = new TestSocket("127.0.0.1", 7);
// send the command
socket.WriteToCommandStream
( "11111111112222222222333333333344444444445555555555666666666677777777778888888
88899999999990000000000" );
// actually send the command buffer to the receiving server
socket.FlushCommandStream();
// get the results back
String replyFromServer = socket.ReadReply().toString();
// clean up
socket.close();
}
}
Here is the program where the bug occurs. The stack overflow occurs on line 82
of this program, e.g. on the line with inputStream.close().
package princeton.com.x;
import java.io.*;
import java.net.*;
import princeton.com.x.TestSocketReader;
import princeton.com.x.TestSocketWriter;
public class TestSocket extends Socket
{
StringWriter debugOutputStream;
TestSocketWriter outputStream;
TestSocketReader inputStream;
public TestSocket(String address, int port) throws IOException
{
// connect to the parent class socket at the address and port given
super(address, port);
// connect buffered streams to a server ...
// note that the server communicates using 8-bit bytes, but we want to
use Java strings, which are 16-bit,
// so we have to account for the conversion using OutputStreamWriter and
InputStreamReader.
outputStream = new TestSocketWriter(new OutputStreamWriter(
super.getOutputStream() ));
inputStream = new TestSocketReader(new InputStreamReader(
super.getInputStream() ));
// for debugging
debugOutputStream = new StringWriter();
}
public StringBuffer ReadReply() throws IOException
{
StringBuffer result = inputStream.ReadReply();
// for debugging
System.out.println(result);
return result;
}
/*
* public void WriteCommandBatch(String commandBatch) throws IOException
* {
* // for debugging
* System.out.println(commandBatch);
*
* outputStream.WriteCommandBatch(commandBatch);
* }
*
* public void WriteCommandBatch(StringBuffer commandBatch) throws IOException
* {
* WriteCommandBatch( commandBatch.toString() );
* }
*/
public void WriteToCommandStream(String commandString) throws IOException
{
// for debugging
debugOutputStream.write(commandString);
outputStream.write(commandString);
}
public void WriteToCommandStream(StringBuffer commandString) throws
IOException
{
WriteToCommandStream( commandString.toString() );
}
public void FlushCommandStream() throws IOException
{
// for debugging
System.out.println( debugOutputStream.getBuffer() );
debugOutputStream.close();
debugOutputStream = new StringWriter();
outputStream.flush();
}
public void close() throws IOException
{
debugOutputStream.close();
inputStream.close();
outputStream.close();
super.close();
}
}
Here are the two supporting classes which you need to test this program:
package princeton.com.x;
import java.io.*;
public class TestSocketReader extends BufferedReader
{
public TestSocketReader(Reader streamReader) throws IOException
{
super(streamReader);
}
public StringBuffer ReadReply() throws IOException
{
StringBuffer replyString = new StringBuffer();
char nextChar;
nextChar = (char) read(); // note that read() blocks until a character
is available
while ( nextChar != 0 )
{
replyString.append(nextChar);
nextChar = (char) read();
}
return replyString;
}
}
(new file starts here)
package princeton.com.x;
import java.io.*;
public class TestSocketWriter extends BufferedWriter
{
public TestSocketWriter(Writer streamWriter) throws IOException
{
super(streamWriter);
}
public void flush() throws IOException
{
write(0);
super.flush();
}
/*
* public void WriteCommandBatch(String commandBatch) throws IOException
* {
* write(commandBatch);
* flush();
* }
*/
}
Here is the output from this program in jdk1.4:
11111111112222222222333333333344444444445555555555666666666677777777778888888888
99999999990000000000
11111111112222222222333333333344444444445555555555666666666677777777778888888888
99999999990000000000
java.lang.StackOverflowError
at java.io.InputStreamReader.close(InputStreamReader.java:535)
at java.io.BufferedReader.close(BufferedReader.java:502)
at princeton.com.x.TestSocket.close(TestSocket.java:82)
at java.net.SocketInputStream.close(SocketInputStream.java:190)
at java.io.InputStreamReader.close(InputStreamReader.java:538)
at java.io.BufferedReader.close(BufferedReader.java:502)
at princeton.com.x.TestSocket.close(TestSocket.java:82)
at java.net.SocketInputStream.close(SocketInputStream.java:190)
at java.io.InputStreamReader.close(InputStreamReader.java:538)
...
(1012 lines deleted - repeating sets of the preceding 4 lines)
...
at java.io.BufferedReader.close(BufferedReader.java:502)
at princeton.com.x.TestSocket.close(TestSocket.java:82)
at java.net.SocketInputStream.close(SocketInputStream.java:190)
Exception in thread "main"
This program appears to operate properly in jdk1.3.
(Review ID: 128832)
======================================================================