40
votes

I've been lately trying to learn more and generally test Java's serialization for both work and personal projects and I must say that the more I know about it, the less I like it. This may be caused by misinformation though so that's why I'm asking these two things from you all:

1: On byte level, how does serialization know how to match serialized values with some class?

One of my problems right here is that I made a small test with ArrayList containing values "one", "two", "three". After serialization the byte array took 78 bytes which seems awfully lot for such low amount of information(19+3+3+4 bytes). Granted there's bound to be some overhead but this leads to my second question:

2: Can serialization be considered a good method for persisting objects at all? Now obviously if I'd use some homemade XML format the persistence data would be something like this

<object>
    <class="java.util.ArrayList">
    <!-- Object array inside Arraylist is called elementData -->
    <field name="elementData">
        <value>One</value>
        <value>Two</value>
        <value>Three</value>
    </field>
</object>

which, like XML in general, is a bit bloated and takes 138 bytes(without whitespaces, that is). The same in JSON could be

{
    "java.util.ArrayList": {
        "elementData": [
            "one",
            "two",
            "three"
        ]
    }
}

which is 75 bytes so already slightly smaller than Java's serialization. With these text-based formats it's of course obvious that there has to be a way to represent your basic data as text, numbers or any combination of both.

So to recap, how does serialization work on byte/bit level, when it should be used and when it shouldn't be used and what are real benefits of serialization besides that it comes standard in Java?

9

9 Answers

48
votes

I would personally try to avoid Java's "built-in" serialization:

  • It's not portable to other platforms
  • It's not hugely efficient
  • It's fragile - getting it to cope with multiple versions of a class is somewhat tricky. Even changing compilers can break serialization unless you're careful.

For details of what the actual bytes mean, see the Java Object Serialization Specification.

There are various alternatives, such as:

(Disclaimer: I work for Google, and I'm doing a port of Protocol Buffers to C# as my 20% project, so clearly I think that's a good bit of technology :)

Cross-platform formats are almost always more restrictive than platform-specific formats for obvious reasons - Protocol Buffers has a pretty limited set of native types, for example - but the interoperability can be incredibly useful. You also need to consider the impact of versioning, with backward and forward compatibility, etc. The text formats are generally hand-editable, but tend to be less efficient in both space and time.

Basically, you need to look at your requirements carefully.

11
votes

The main advantage of serialization is that it is extremely easy to use, relatively fast, and preserves actual Java object meshes.

But you have to realize that it's not really meant to be used for storing data, but mainly as a way for different JVM instances to communicate over a network using the RMI protocol.

5
votes

see the Java Object Serialization Stream Protocol for a description of the file format an grammar used for serialized objects.

Personally I think the built-in serialization is acceptable to persist short-lived data (e.g. store the state of a session object between to http-requests) which is not relevant outside your application.

For data that has a longer live-time or should be used outside your application, I'd persist either into a database or at least use a more commonly used format...

4
votes

How does Java's built-in serialization works?

Whenever we want to serialize an object, we implement java.io.Serializable interface. The interface which does not have any methods to implement, even though we are implementing it to indicate something to compiler or JVM (known as Marker Interface). So if JVM sees a Class is Serializable it perform some pre-processing operation on those classes. The operation is, it adds the following two sample methods.

private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.writeObject(name); // object property
        stream.writeObject(address); // object property
    }

    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        name = (String) stream.readObject(); // object property
        address = (String) stream.readObject();// object property
    }

When it should be used instead of some other persistence technique?

The built in Serialization is useful when sender and receiver both are Java. If you want to avoid the above kind of problems, we use XML or JSON with the help of frameworks.

0
votes

I bumped into this dilemma about a month ago (see the question I asked).

The main lesson I learned from it is use Java serialization only when necessary and if there's no other option. Like Jon said, it has it's downfalls, while other serialization techniques are much easier, faster and more portable.

0
votes

Serializing means that you put your structured data in your classes into a flat order of bytecode to save it.

You should generally use other techniques than the buildin java-method, it is just made to work out of the box but if you have some changing contents or changing orders in future in your serialized classes, you get into trouble because you'll cannot load them correctly.

0
votes

The advantage of Java Object Serialization (JOS) is that it just works. There are also tools out there that do the same as JOS, but use an XML format instead of a binary format.

About the length: JOS writes some class information at the start, instead of as part of each instance - e.g. the full field names are recorded once, and an index into that list of names is used for instances of the class. This makes the output longer if you write only one instance of the class, but is more efficient if you write several (different) instances of it. It's not clear to me if your example actually uses a class, but this is the general reason why JOS is longer than one would expect.

BTW: this is incidental, but I don't think JSON records class names (as you have in your example), and so it might not do what you need.

0
votes

The reason why storing a tiny amount of information is serial form is relatively large is that it stores information about the classes of the objects it is serialising. If you store a duplicate of your list, then you'll see that the file hasn't grown by much. Store the same object twice and the difference is tiny.

The important pros are: relatively easy to use, quite fast and can evolve (just like XML). However, the data is rather opaque, it is Java-only, tightly couples data to classes and untrusted data can easily cause DoS. You should think about the serialised form, rather than just slapping implements Serializable everywhere.

0
votes

If you don't have too much data, you can save objects into a java.util.Properties object. An example of a key/value pair would be user_1234_firstname = Peter. Using reflection to save and load objects can make things easier.