Serialisation

Hey all

When i am trying to serialize a Object[] (witch exist out of other Object[])

i sometimes get a EofException and sometimes not.

It's really frustrating. The Object[] is typical something like this

Object[] rows = new Object[]{ new Object[] {String, String, String, Short, Date},

new Object[]{...

}

When i change the date inside the object[] to the current date all goes well

but when i change it to whatever other (valid) value it goes wrong?

Error trace looks like this...

java.io.EOFException

at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2507)

at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1870)

at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1844)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1718)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1882)

at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1844)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1718)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1882)

at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1844)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1718)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1882)

at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1844)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1718)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1882)

at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1844)

at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1718)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1304)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1633)

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1298)

at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)

If anyone could help me with this, i would be very grateful.

[3290 byte] By [Jos...a] at [2007-11-26 20:49:19]
# 1
The exception is happening when deserailizing. It just means that what you're trying to read wasn't written to the stream. Did you get an exception when serializing? and maybe ignore it?
ejpa at 2007-7-10 2:13:07 > top of Java-index,Java Essentials,Java Programming...
# 2

Hi

Yes sorry you are right it's deserailizing, but i don't think its a question of not writing all to the stream.

I completely analyzed the input and outputstream, when all goes well (rows with the current date) i am writing 21078 bytes to the stream and also exactly reading

the 21078 bytes.

When i use a different date i also write 21078 bytes to the stream but the deserailizing process tries to read more?

I really don't know but this seems like a bug to me.

Jos...a at 2007-7-10 2:13:07 > top of Java-index,Java Essentials,Java Programming...
# 3
Can you reduce this to a very short example program that demonstrates "the bug"? If so, post it.
DrLaszloJamfa at 2007-7-10 2:13:07 > top of Java-index,Java Essentials,Java Programming...
# 4

Hello

Code is like this,

(I am reading from a RandomAccessFile called file.)

public Object[] getContents() {

int len = file.length();

ArrayList<Object[]> list = new ArrayList<Object[]>();

while(file.getFilePointer() < len){

doRead(); // this fills up a String name, a short version and a long

// modified

// .. Breaking up String name in 3 parts (path, nm, type)

Object[] row = new Object[]{

path,

nm,

type,

new Short(version) ,

new Date(modified)

}

list.add(row);

}

// .. About 200 rows in list.

Object[] ret = list.toArray(new Object[list.size()]);

return ret;

}

//....

public void someMethod() throws Exception{

Object[] data = getContents();

ObjectOutputStream oos = new ObjectOutputStream(

new MyOutputStream());

//MyOutputStream is simple a extension of OutputStream

// that buffers all the bytes written to it so they can be send across

// the network.

oos.writeObject(data);

oos.close();

...

}

// ... Method on client side receives the serialised Object,

//the byte[] is set to a inputStream and returns -1 when the end

//of the byte[] is reached

public void receive(byte[] bb) throws Exception {

ObjectInputStream ois = new ObjectInputStream(

new MyInputStream(bb));

Object[] rows = (Object[])ois.readObject();

ois.close();

}

Jos...a at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 5

> ObjectOutputStream oos = new ObjectOutputStream(

>new MyOutputStream());

> // MyOuttputStream is simple a extension of OutputStream

> // that buffers all the bytes written to it so they can be send across

>// the network.

>oos.writeObject(data);

>oos.close();

How does your 'MyOutputStream' handle flush()es? I suspect that

your MyOutputStream forgets to write the last (probably incomplete)

buffer before it closes.

kind regards,

Jos ( < not kidding you ;-)

JosAHa at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 6

Why does MyOutputStream has to handle flushes at all?

The only method implemented there is the one declared abstract in java.io.OutputStream.

public void write(int b) throws IOException

Closing the ObjectOutputStream causes this method to be triggered, also writing the last bytes.

Where do i go wrong, HELP.

Jos...

Jos...a at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 7

All buffered output, must be flushed with a call to flush() before you close the stream. The Input side is simply reading Objects, so it doesn't matter whether it's buffered or not, only that there are enough bytes to read.

Have you tried writing the output to a file and seeing how big it is? 21078 does seem to be an odd number of bytes if its a buffering issue (it only divides by 18), but if the resulting file size divides by a power of two (usually 512, 1024 or 2048) then its almost certainly buffering.

YoungWinstona at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 8

Forget the flush. Closing the ObjectOutputStream will flush and close it and all the strreams it is built over including the MyOutputStream. Although what's wrong with using BuffferedOutputStream instead of writing your own is a mystery to me.

I'm more interested in how the OP does deserialization from a RandomAccessFile, and why.

ejpa at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 9

hello

I agree, lets forget the flush.

Why do i use my own outputstream instead of a buffered one.

Well its not like i have to so some expensive IO operations the only thing i want is the serialized byte[], so i can send it across the network. So if i should use the BufferedStream i also should have to create a derived class to get access to the stored buffer.

For clarity i am not serializing a RandomAccesFile. I am writing a backup application, using one RandomAccessFile for storing all data and a other file to describe the first one.

The plan was to read that second file to get a view of the contents and sending that information in the form of a Object[].

To get back to the point, i 'am really beginning to believe that the serialization and / or the deserialization process is having problems with primitive values of type long.

I 've changed the code in...

Object[] row = new Object[]{

path,

nm,

type,

new Short(version) ,

String.valueOf(modified) //new Date(modified)

}

leaving it up to the client converting it back into a Date

This works fine and i am happy for now. But if someone could explain to me what's really the matter, don' t hesitate.

Jos...

Jos...a at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 10

I don't understand a word of that.

(a) Why don't you use anObjectOutputStream over a BufferedOutputStream and write directly to the network like everybody else? Forget the buffer, forget the bytes, they will disappear down the network without you having to write an extra class.

(b) I didn't ask why you were serializing a RandomAccessFile.The question would be meaningless. I asked why you were deserializing from a RandomAccessFile. This is rather hard to do as you can't just stack an ObjectInputStream over it, you have to deal with the bytes directly and interpose a ByteArrayOutputStream or some such.

(c) As serialization has been working with primitive and object data for about eleven years, it's a pretty fair bet that all your problems are stemming from these extra complication you're introducing into both phases of serialization. But as you haven't shown us any of it, it's impossible to be more specific.

ejpa at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 11

OK

Explaining is not my best quality, you also should have noticed that English is not my native language. Let me try again.

a) I am working with channels (java.nio) and in order to use them you have to fill up ByteBuffers and that can be done with a byte[].

b) I don't understand, why do you think i am deserializing from a RandomAccessFile?

I only try to deserialize some data read from a RandomAccessFile

c) I don't see the extra complexity, i am also certainly not convinced that there

really is a problem with de (de)serialization process,

i only state

- sometimes there is a problem using an long (new Date(modified)

- sometimes there isn't (new Date())

- there is (so far i know) never a problem using a String

Jos...a at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...
# 12

> a) I am working with channels (java.nio) and in order

> to use them you have to fill up ByteBuffers and that

> can be done with a byte[].

OK

> b) I don't understand, why do you think i am

> deserializing from a RandomAccessFile?

> I only try to deserialize some data read from a

> RandomAccessFile

I can't see any difference between these two statements, and I stlll don't know why you can't use a FileInputStream and an ObjectInputStream on top of it.

> i only state

> - sometimes there is a problem using an long (new

> Date(modified)

Until you show us the code that serializes the object as well as the code that deserializes it we are all guessing.

ejpa at 2007-7-10 2:13:08 > top of Java-index,Java Essentials,Java Programming...