hinsbergen
hinsbergen

Reputation: 147

Overhead in java ObjectOutputStream?

I am puzzled by the behavior of ObjectOutputStream. It seems like it has an overhead of 9 bytes when writing data. Consider the code below:

float[] speeds = new float[96];
float[] flows = new float[96];

//.. do some stuff here to fill the arrays with data

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos=null;
try {
    oos = new ObjectOutputStream(baos);
    oos.writeInt(speeds.length);
    for(int i=0;i<speeds.length;i++) {
        oos.writeFloat(speeds[i]);
    }
    for(int i=0;i<flows.length;i++) {
        oos.writeFloat(flows[i]);
    }
    oos.flush();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if(oos!=null) {
            oos.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

byte[] array = baos.toByteArray();

The length of the array is always 781, while I would expect it to be (1+96+96)*4 = 772 bytes. I can't seem to find where the 9 bytes go.

Thanks!

--edit: added if(oos!=null) { ... } to prevent NPE

Upvotes: 5

Views: 3601

Answers (4)

Joni
Joni

Reputation: 111279

Java's serialization stream begins with a 4-byte header (2-byte "magic number" followed by a 2-byte version). The header is followed by a sequence of block-data and objects entries. There are two kinds of blocks-data entries: "short" and "long." Short blocks have a 2-byte overhead per block and the block can be at most 255 bytes long. Long blocks have a 5-byte overhead but they can be up to 4 GB in length. How long the "long" block can be in practice depends on the size of ObjectOutputStream's internal buffers.

In this case you only have one long data-block entry, so the overhead you see is 4 bytes from the stream header and 5 from the data block, 9 bytes in total.

You'll find the full documentation here: http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html

Upvotes: 0

Andy Thomas
Andy Thomas

Reputation: 86409

The ObjectOutputStream writes a header at the beginning.

You can eliminate this header by subclassing ObjectOutputStream and implementing writeStreamHeader().

Upvotes: 2

Piotr Praszmo
Piotr Praszmo

Reputation: 18320

ObjectOutputStream is used to serialize objects. You shouldn't make any assumptions how the data is stored.

If you want to store just the raw data use DataOutputStream instead.

Upvotes: 3

A.H.
A.H.

Reputation: 66263

The JavaDoc for ObjectOutputStream tells you:

Primitive data, excluding serializable fields and externalizable data, is written to the ObjectOutputStream in block-data records. A block data record is composed of a header and data. The block data header consists of a marker and the number of bytes to follow the header. Consecutive primitive data writes are merged into one block-data record. The blocking factor used for a block-data record will be 1024 bytes. Each block-data record will be filled up to 1024 bytes, or be written whenever there is a termination of block-data mode. Calls to the ObjectOutputStream methods writeObject, defaultWriteObject and writeFields initially terminate any existing block-data record.

So the blocking stuff might be your missing overhead.

Upvotes: 0

Related Questions