Jazoon 2012: Serialization: Tips, Traps, and Techniques

Every once in a while, you learn something new even though you thought you’d know it all. That’s what happened to me during the talk “Serialization: Tips, Traps, and Techniques” by Ian Partridge.

Serialization is such a basic, old technique that it’s surprising that you can learn something new about it. In a nutshell, serialization converts between object graphs and byte streams.

Unfortunately, the API is one of the oldest in the Java runtime. And it’s not one of the best. On the other hand, it’s used in many places like RMI, EJB, SDO, JPA and distributed caching.

What did I learn? Let’s see.

Did you know that it’s possible to serialize a class (without error) that you can’t read back in? It’s actually pretty simple to do: Don’t provide a default constructor (you know, those without any arguments).

You also shouldn’t try to serialize non-static inner classes because they keep a hidden reference to the outer instance.

When you use serialization, then you must take into account that the serialized form becomes part of the public API. This means that private and even final fields are suddenly part of your API that you need to document. Why? Because ObjectInputStream creates an instance using the default constructor and then it sets the final fields using Unsafe.putObject().

If you check the parameters in your constructor, then you will have to repeat them in readObject(). On top of that, you can’t trust the instances which you get from the Serialization API. An attacker can manipulate the byte stream to get references to internal data structures which you most certainly don’t want to expose.

There were *Unshared() methods added with Java 1.4 to solve these but they don’t work. Forget about them.

Anything else? Oh, yes: The serialVersionUID. Besides all the known problems, there is another one:

private static int COUNTER = 0;</pre>
public static class Version1 implements Serializable {
    void foo() {
        COUNTER = COUNTER + 1;
    }
}

If someone fixes this code to

private static int COUNTER = 0;</pre>
public static class Version1 implements Serializable {
    void foo() {
        COUNTER += 1;
    }
}

then deserialization fails for some versions of Java because the generated hidden accessor methods change.

The Serializable Proxy Pattern solves many of the problems.

If you use proxies, consider using Externalizable instead of Serializable

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 336 other followers