EOFException with ObjectInputStream

Hi,

I got this problem with EOFException while I'm having a file transfer from server to client but I have no idea how it can come up with that exception. If you guys know anything might be able to solve it, I will be grateful to listen to the solution.

The exception below was coming from server console.

java.io.EOFException

at java.io.ObjectInputStream$BlockDataInputStream.readFully(Unknown Source)

at java.io.ObjectInputStream.readArray(Unknown Source)

at java.io.ObjectInputStream.readObject0(Unknown Source)

at java.io.ObjectInputStream.defaultReadFields(Unknown Source)

at java.io.ObjectInputStream.readSerialData(Unknown Source)

at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)

at java.io.ObjectInputStream.readObject0(Unknown Source)

at java.io.ObjectInputStream.defaultReadFields(Unknown Source)

at java.io.ObjectInputStream.readSerialData(Unknown Source)

at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)

at java.io.ObjectInputStream.readObject0(Unknown Source)

at java.io.ObjectInputStream.readObject(Unknown Source)

at com.otnateos.model.connection.SocketConnection.run(SocketConnection.java:98)

at java.lang.Thread.run(Unknown Source)

Message was edited by:

ot6

[1329 byte] By [ot6a] at [2007-11-26 16:29:36]
# 1

You are trying to read some serialized objects (you say file transfer)? To begin with, the ObjectInputStream is waiting for a few bytes (think its 4 bytes that are sent from an ObjectOutputStream) before it reads the objects, and if it doesn't get those, you might get this exception (maybe you dont get any data at all).

You got more info about how the data you read has been created?

You could try to read the data into a ByteArrayOutputStream and then look at how much data you got and read it with your ObjectInputStream from a ByteArrayInputStream with the data from the ByteArrayOutputStream.

abnormala at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 2

> You are trying to read some serialized objects (you

> say file transfer)?

well, it is true that it was using serialized object. thanks to point that out.

basically i had this PDF file that i read as byte array and i attach it into an object and i send this object as serialized object from server to client and the other way around.

> To begin with, the

> ObjectInputStream is waiting for a few bytes (think

> its 4 bytes that are sent from an ObjectOutputStream)

> before it reads the objects, and if it doesn't get

> those, you might get this exception (maybe you dont

> get any data at all).

Are you saying that it could be that the packet being sent from the server/client was lost in transfer or something like "the sender cannot send the object completely?

> You got more info about how the data you read has

> been created?

> You could try to read the data into a

> ByteArrayOutputStream and then look at how much data

> you got and read it with your ObjectInputStream from

> a ByteArrayInputStream with the data from the

> ByteArrayOutputStream.

All that i can notice from the byte transfer sometime the byte being received is a lot smaller than it suppose to be / sometimes bigger (for example, file = 1MB, transfered = 2MB)

Do you guys know whether this behavior mostly happened because of transfer problem only / file reading / because server is clustered / other thing?

Thanks beforehand

ot6a at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 3

I don't know your reason for using serialized objects to transfer a byte array, but if it's just a matter of transfering this byte array, you don't need any object streams.

But to continue with your problem:

Make sure you read the objects in the same order that you send them.

The classes you have made that implements Serializable must be exactly the same on both the server and client (unless you have the same serialVersionUID both places, and its the same set of variables you transfer).

Don't use any Reader/Writer classes since it will do some character conversions (stick to InputStream and OutputStream).

EOFException could of course also happen because the other end lost the connection to internet or killed the program. But then it should work where this doesnt happen.

If you have some code where you send and receive the object, it will be easier to see what could be wrong.

abnormala at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 4

> If you have some code where you send and receive the

> object, it will be easier to see what could be wrong.

Sorry, it's gonna be a long post, I give excerpt of the code with example of serialized objects, I also used FilterInputStream/FilterOutputStream to monitor the progress of transfer.

class MessageCollection implements Serializable {

private static final long serialVersionUID = 1;

public Hashtable messages;

public MessageCollection() {

messages = new Hashtable();

}

public void addMessage(String key, String message) {

messages.put(key, message);

}

}

class Attachment implements Serializable {

private static final long serialVersionUID = 1;

byte[] content;

String fileName;

String fileLocation;

int fileSize;

}

/* this is the server */

class SocketThread extends Thread {

private boolean isListening = true;

private Socket socket = null;

private ObjectOutputStream oos = null;

private ObjectInputStream ois = null;

public SocketThread(Socket socket) {

this.socket = socket;

}

public void run() {

try {

oos = new ObjectOutputStream(socket.getOutputStream());

ois = new ObjectInputStream(socket.getInputStream());

Object inputObject;

sendAuthenticationRequest();

while(((inputObject = ois.readObject()) != null) && isListening) {

handleIncoming(inputObject, this.getName());

}

disconnect();

} catch (SocketException se) {

disconnect();

} catch (IOException ioe) {

if(ioe.getMessage() == null) {

disconnect();

} else {

System.err.println("!SocketThread![IOE] " + ioe.getMessage());

disconnect();

}

} catch(Exception e) {

System.err.println("!SocketThread! error "+e.getMessage());

disconnect();

}

}

private void handleIncoming(Object object, String clientName) {

System.out.println("Receive from: "+clientName + " |Data: "+object.getClass().getName());

}

public void write(Object object) {

try {

oos.writeObject(object);

} catch(Exception e) {

System.err.println("!SocketThread! write error "+e.getMessage());

disconnect();

}

}

public void disconnect() {

try {

oos.close();

oos = null;

} catch(Exception ioe) { }

try {

ois.close();

ois = null;

} catch(Exception ioe) { }

try {

socket.close();

socket = null;

} catch(Exception ioe) { }

}

private void sendAuthenticationRequest() {

MessageCollection message = new MessageCollection();

message.addMessage("info_Welcome", "Welcome, you are connected to:" + this.socket.toString());

message.addMessage("info_AuthRequest", "Please send authentication details.");

write(message);

}

}

/*

* This is the client

*/

class SocketConnection implements Runnable {

public int PROGRESS = 0;

private Thread thread;

private Socket socket;

private ObjectOutputStream oos;

private ObjectInputStream ois;

private SocketProgressInputStream fis;

private SocketProgressOutputStream fos;

private String host;

private int port;

private boolean connected;

private static final String httpString = "http://";

public SocketConnection(final String serverHost, final int serverPort) {

this.host = serverHost.indexOf(httpString) != -1 ? serverHost.substring(httpString.length()) : serverHost;

this.port = serverPort;

try {

socket = new Socket();

socket.connect(new InetSocketAddress(host, port), 30000);

fos = new SocketProgressOutputStream(socket.getOutputStream());

oos = new ObjectOutputStream(fos);

connected = true;

thread = new Thread(this);

thread.start();

} catch(Exception e) {

System.err.println("SocketConnection fail to start!");

}

}

public void run() {

try {

fis = new SocketProgressInputStream(socket.getInputStream());

ois = new ObjectInputStream(fis);

Object object;

while((object = ois.readObject()) != null && connected) {

System.out.println("SocketConnection reading: "+object.getClass().getName());

}

} catch(UnknownHostException uhe) {

System.err.println("!"+getClass().getName()+"! UnknownHostException : " + uhe.getMessage());

} catch(StreamCorruptedException sce) {

System.err.println("!"+getClass().getName()+"! StreamCorruptedException : "+sce.getMessage());

} catch(SocketException se) {

if(se.getMessage().toLowerCase().equals("socket closed")) {

} else {

System.err.println("!"+getClass().getName()+"! > SocketException : "+se.getMessage());

se.printStackTrace();

}

} catch(NullPointerException ne) {

ne.printStackTrace();

} catch(IOException ex) {

if(ex.getMessage() != null) {

ex.printStackTrace(System.out);

System.err.println("!"+getClass().getName()+"! > IOException : "+ex.getMessage());

}

} catch(Exception e) {

e.printStackTrace();

} finally {

close();

}

}

public void write(Object object) {

try {

oos.writeObject(object);

} catch(Exception e) {

System.err.println("!SocketConnection! writing object: "+object.getClass().getName() +"("+e.getMessage()+")");

}

}

public void close() {

connected = false;

try {

oos.close();

oos = null;

ois.close();

ois = null;

socket.close();

socket = null;

} catch(Exception e) {

}

}

/*

* These filters are used to monitor progresses in sending and receiving

*/

private class SocketProgressInputStream extends FilterInputStream {

protected SocketProgressInputStream(InputStream in) {

super(in);

}

public int read() throws IOException {

PROGRESS += 1;

return super.read();

}

public int read(byte[] b) throws IOException {

PROGRESS += b.length;

return super.read(b);

}

public int read(byte[] b, int off, int len) throws IOException {

PROGRESS += len;

return super.read(b, off, len);

}

}

private class SocketProgressOutputStream extends FilterOutputStream {

public SocketProgressOutputStream(OutputStream out) {

super(out);

}

public void write(int b) throws IOException {

PROGRESS += 1;

super.write(b);

}

public void write(byte[] b) throws IOException {

PROGRESS += b.length;

super.write(b);

}

public void write(byte[] b, int off, int len) throws IOException {

PROGRESS += (len-off);

super.write(b, off, len);

}

}

}

ot6a at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 5

Nothing major wrong here. Some comments:

> if(ioe.getMessage() == null) {

Can this really happen?

> try {

> ois.close();

> ois = null;

> } catch(Exception ioe) { }

> try {

> socket.close();

> socket = null;

> } catch(Exception ioe) { }

This is all redundant once you've closed the output stream.

> } catch(UnknownHostException uhe) {

This can't happen on a read.

> } catch(NullPointerException ne) {

Don't catch these, fix the bug!

> } catch(IOException ex) {

> if(ex.getMessage() != null) {

Can this really happen?

> try {

> ois.close();

> ois = null;

> socket.close();

> socket = null;

Redundant: see above.

> public int read() throws IOException {

> PROGRESS += 1;

Very misleading. There is no progress at all until super read() returns, and if it returns -1 or throws an exception there was no progress at all.

> public int read(byte[] b) throws IOException {

> PROGRESS += b.length;

Ditto

> public int read(byte[] b, int off, int len) throws IOException {

> PROGRESS += len;

Ditto

> public void write(int b) throws IOException {

> PROGRESS += 1;

Very misleading. There is no progress at all until super write() returns, and if it throws an exception there was no progress at all.

> public void write(byte[] b) throws IOException {

> PROGRESS += b.length;

Ditto

> public void write(byte[] b, int off, int len) throws IOException {

> PROGRESS += (len-off);

Ditto.

I suspect there's something wrong with your setting up of the Attachment objects.

ejpa at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 6

> Nothing major wrong here. Some comments:

> .......

Thanks for the comments, that's really helping specially for the FilterStream which i just realised that it was wrong the way I calculated the bytes.

> I suspect there's something wrong with your setting

> up of the Attachment objects.

The way I read the file and attach it into attachment is reading the file and write it into ByteArrayOutputStream. The code below is excerpt from the file reading mechanism

class AttachmentWriter {

public static Attachment convertToAttachment(String filePath) throws Exception {

FileInputStream fileInputStream = new FileInputStream(new File(filePath));

BufferedInputStream bis = new BufferedInputStream(fileInputStream);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

int c;

while((c = bis.read()) != -1) {

baos.write(c);

}

bis.close();

baos.flush();

Attachment attch = null;

attch.fileName = filePath;

attch.fileLocation = filePath;

attch.content = baos.toByteArray();

attch.fileSize = baos.size();

return attch;

}

}

ot6a at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 7

> Thanks for the comments, that's really helping

> specially for the FilterStream which i just realised

> that it was wrong the way I calculated the bytes.

I meant to add that you should increment PROGRESS by the actual number of bytes read (if positive), not by the implicit or explicit length supplied.

I still can't see anything major wrong with your code. What about where you write the attachment to the file at the receiver?

ejpa at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 8

> I meant to add that you should increment PROGRESS by

> the actual number of bytes read (if positive), not by

> the implicit or explicit length supplied.

Are you talking about the reading in the FilterInputStream ?

I change my code to :

private class SocketProgressInputStream extends FilterInputStream {

protected SocketProgressInputStream(InputStream in) {

super(in);

}

public int read() throws IOException {

int i = super.read();

if(i != -1) sendMessage(PROGRESS + 1);

return i;

}

public int read(byte[] b) throws IOException {

int i = super.read(b);

if(i != -1) sendMessage(PROGRESS + i);

return i;

}

public int read(byte[] b, int off, int len) throws IOException {

int i = super.read(b, off, len);

if(i != -1) sendMessage(PROGRESS + i);

return i;

}

}

> I still can't see anything major wrong with your

> code. What about where you write the attachment to

> the file at the receiver?

hmn.. actually I just realise that the message on the first post was exception thrown on the client side. the error message from the server console was

!SocketThread! write error null

so the client (receiver) didn't even managed to construct the whole object because of the exception thrown on the first post.

ot6a at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...
# 9
Finally I found out what caused the exception. I had 2 threads from the server which sending objects to the client. The second object was written just before the server finish transferring the first object.
ot6a at 2007-7-8 22:54:00 > top of Java-index,Core,Core APIs...