If I had a dollar for every time I'd seen this mistake, I'd be typing this
article on a more expensive laptop. The mistake usually looks something like this:
OutputStream out = new FileOutputStream(f);
BufferedOutputStream bout = new BufferedOutputStream(out);
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.write(object);
out.close();
The problem here is that we've closed the wrong stream. In between the actual
FileOutputStream and the object writing, there is a layer of buffering.
Thus, when we close the underlying output stream, there is a risk that some of
the data is still "stuck" in the buffer.
The solution is simple, and is how you should always handle closing
streams: ALWAYS close the stream that was created last, in this
case, the ObjectOutputStream. This way, each layer of streaming has
a chance to pass any buffered data down to the stream below it (and by definition,
the close() method must do so). Note that you don't need
to close every stream— just the outer one.
This is also a mistake I've seen time and time again.
It happens when you're manually chopping up an input stream
into sections and then passing part of the stream to an ObjectInputStream.
Each section might be preceded by a four-byte length marker, for example:
public Object readObject(InputStream in) throws IOException, ... {
int objDataLen = readInt(in);
byte[] objData = new byte[objDataLen];
in.read(objData);
ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objData));
return oin.readObject();
}
Here, our capital sin is that we assume that the read() method
will fill the array. It won't necessarily, and we end up with a partial
object stream. The problem can be especially difficult to track down when the bytes are
coming in over a network, because the problem will be intermittent and essentially
random.
If this problem occurs at some point in the stream, then it will
have a knock-on effect on later parts of the stream. The solution is to
be careful to always check the return value of InputStream.read()
when reading into an array.