Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: efficiency of writeObject vs writeExternal

It's said that Java's default serialization mechanism is not very efficient because a)it discovers which fields to write/read through reflection which is usually slow b) it writes extra data to stream.

One way to make it more efficient is to implement Externalizable and its writeExternal/readExternal methods.

Here's the question: if I instead provide 'writeObject/readObject' methods and don't call deafiltWriteObject/defaultReadObject in them, then this mechanism won't use reflection to figure out which fields to write/read, plus it won't write extra data to stream (or will it? not sure). So from an efficiency perspective, is implementing writeObject/readObject mentioned above same as implementing Externalizable? Or does the latter option give some more practical benefits which the former doesn't?

EDIT: a difference, ofcourse, is when a Serializable class implementing readObject/writeObject is subclassed, and if the subclass has its own readObject/writeObject, they don't need to call super's readObject/writeObject. Not so if the super/subclass instead implement Externalizable. In this case, super's writeExternal/readExternal need to be explicitly called. However, this difference is irrelevant from an efficiency point of view.

like image 677
shrini1000 Avatar asked May 04 '12 06:05

shrini1000


3 Answers

There is still some over head in choosing which class/writeObject/readObject to call next. but it is significantly reduced.

This can perform the same as Externalizable depending on what you are doing and whether you use the extra options it gives you. e.g. readObject assumes you to create a new object each time, Externalizable has readResolve which means you can reuse objects.

http://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/input.html

In many cases, recycling objects is the "next" step in speeding up deserialization. (Assuming that's an option for you)

http://vanillajava.blogspot.co.uk/2011/10/recycling-objects-to-improve.html

like image 93
Peter Lawrey Avatar answered Sep 17 '22 14:09

Peter Lawrey


Found a couple of things while experimenting and going through serialization mechanism's code:

1) if the object is found to be Externalizable, it's cast to Externalizable, and corresponding method is called on it; whereas for Serializable object, it's reflectively checked if it has readObject/writeObject. So maybe this makes it slightly slower,

2) the amount of data written for Externalizable is a little less than Serializable with readObject/writeObject (I found a difference of 1 byte for the following code when I wrote object of B).

For Externalizable:

static class A implements Externalizable
{
    @Override
    public void writeExternal(ObjectOutput out) throws IOException 
    {
        System.out.println("A write called");
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    {
        System.out.println("A read called");
    }       
}

static class B extends A implements Externalizable
{       
    @Override
    public void writeExternal(ObjectOutput out) throws IOException 
    {
        super.writeExternal(out);
        System.out.println("B write called");
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
    {
        super.readExternal(in);
        System.out.println("B read called");
    }       
}

For Serializable:

static class A implements Serializable
{
    private void writeObject(ObjectOutputStream out) throws IOException 
    {
        System.out.println("A write called");
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    {
        System.out.println("A read called");
    }       
}

static class B extends A implements Serializable
{       
    private void writeObject(ObjectOutputStream out) throws IOException 
    {           
        System.out.println("B write called");
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
    {           
        System.out.println("B read called");
    }       
}
like image 38
shrini1000 Avatar answered Sep 17 '22 14:09

shrini1000


The major difference, in terms of class design, is that Serializable will work on any class, whereas Externalizable only works on mutable classes with public default (no-arg) constructors.

like image 34
nilskp Avatar answered Sep 19 '22 14:09

nilskp