wickstopher
wickstopher

Reputation: 999

Why does order of instantiation seem to matter for input and output streams in Java?

I have the following code that works (please assume that hostname and port are initialized to their proper values, and that Message is a serializable class):

//Example 1 - everything works as expected
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
    ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());                  
    outStream.writeObject(message);
    outStream.flush();

    ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());
    Object response = inStream.readObject();
}

When I move the instantiation of the ObjectInputStream to occur immediately after the ObjectOutputStream instantiation, execution of my application hangs indefinitely:

//Example 2 - client locks up
Message message = new Message();
try(Socket serverSocket = new Socket(hostname, port))
{
    ObjectOutputStream outStream = new ObjectOutputStream(serverSocket.getOutputStream());                  
    ObjectInputStream inStream = new ObjectInputStream(serverSocket.getInputStream());

    outStream.writeObject(message);
    outStream.flush();

    Object response = inStream.readObject();
}

I'm looking for a good explanation as to why the second example locks up consistently, and the first example seems to work without a hitch. Strangely, if I use a debugger (Eclipse debugger) on the client and server with this second example, I'm seeing the message make it through to the server, so the writeObject() call is being executed. However, in the client, the debugger gets stuck on the constructor for the ObjectInputStream.

Upvotes: 2

Views: 715

Answers (2)

display101
display101

Reputation: 2085

If we go and have a read of the API docs for the ObjectInputStream constructor

The important part:

This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.

Upvotes: 4

user207421
user207421

Reputation: 310988

Constructing an ObjectOutputStream writes a header to the stream. Constructing an ObjectInputStream reads it. If both ends construct the ObjectInputStream first, you will therefore get a deadlock.

Solution: construct the ObjectOutputStream first, at both ends, to make sure it can't happen.

Upvotes: 1

Related Questions