Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Creating a new ObjectInputStream Blocks

I'm trying to create a new ObjectInputStream using an InputStream retrieved from a Socket. Here is my code:

This is the constructor for my MessageGetterSender class. The program does not get to Checkpoint 4.

public MessageGetterSender(Socket socket) {

    System.out.println("MessageGetterSender: Checkpoint 1");

    this.socket = socket;

    // Get input and output streams
    try {
        System.out.println("MessageGetterSender: Checkpoint 2");

        InputStream is = socket.getInputStream();

        System.out.println("MessageGetterSender: Checkpoint 3");

        this.in = new ObjectInputStream(is);

        System.out.println("MessageGetterSender: Checkpoint 4");

    } catch (IOException ioe) {
        System.out.println("Could not get ObjectInputStream on socket: " + socket.getLocalPort());
    }

    try {
        this.out = new ObjectOutputStream(socket.getOutputStream());
    } catch (IOException ioe) {
        System.out.println("Could not get ObjectOutputStream on socket: " + socket.getLocalPort());
    }

    System.out.println("MessageGetterSender: Checkpoint 5");
}

I'm instantiating a new MessageGetterSender object from a class in which I connect to a server to get the socket. Here is the relevant code. It is the constructor for the InstantMessageClass, the class that instantiates the MessageGetterSender object:

public InstantMessageClient(String username) {

try {
    socket = new Socket("localhost", 5555);
} catch (IOException ioe) {
    System.out.println("Error: Could not connect to socket on port: " + serverPort);
}

messageGetterSender = new MessageGetterSender(socket);

...

Since the code does not execute to Checkpoint 4 but it does get to Checkpoint 3, I'm pretty sure the instantiation of the ObjectInputStream is the culprit. I cannot figure out why though. Any ideas? Thanks for the help.

like image 635
ericso Avatar asked Apr 14 '11 03:04

ericso


People also ask

Is readObject In Java?

The method readObject is used to read an object from the stream. Java's safe casting should be used to get the desired type. In Java, strings and arrays are objects and are treated as objects during serialization. When read they need to be cast to the expected type.

What is ObjectInputStream in Java?

The ObjectInputStream class of the java.io package can be used to read objects that were previously written by ObjectOutputStream . It extends the InputStream abstract class.

What is an object stream In Java?

A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. The features of Java stream are – A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.


3 Answers

Just to expand on FatGuy's answer for other Googlers that find this; the solution to this "chicken and egg problem" is to have each side open the output stream first, flush the output stream, and then open the input stream.

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.flush(); ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); 
like image 155
Haywood Slap Avatar answered Nov 02 '22 06:11

Haywood Slap


When you construct an ObjectInputStream, in the constructor the class attempts to read a header that the associated ObjectOutputStream on the other end of the connection has written. It will not return until that header has been read. So if you are seeing the constructor 'hang', it's because the other side of the socket either hasn't used an ObjectOutputStream, or hasn't flushed the data yet.

like image 40
MeBigFatGuy Avatar answered Nov 02 '22 05:11

MeBigFatGuy


You can also delay the initialization of the ObjectInputStream until data is available in the underlying stream.

This approach works regardless of the stream initialization order, and is especially useful if one end of the channel is in library code that you cannot change.

like image 22
Mihai Danila Avatar answered Nov 02 '22 05:11

Mihai Danila