wiki:uka.transport

Fast Object Serialization uka.transport

In the Java API an object serialization mechanism is provided that is able to transparently convert object structures into a linear byte sequence representation and vice versa. For sending objects across the network, this representation can be used. To make his classes serializable, the Java programmer only needs to declare his classes to implement the empty tagging interface java.io.Serializable.

/** A simple serializable class */
public class Param implements java.io.Serializable {
   int    intValue;
   float  floatValue;
   Object objectReference;
}

Although transparency of object serialization is one of Java's beauties, its runtime costs are phenomenal. Since RMI uses Java's built-in object serialization mechanism, usually one third of the overall invocation time of a remote method is spent in marshaling and unmarshaling method arguments. On current hardware, a millisecond is easy to spend in serialization alone. For details please refer to the section "JavaParty papers".

// Assume: Param p, InputStream in, OutputStream out
// 
// Writing an object into a stream and reading it back
new ObjectOutputStream(out).writeObject(p);
Param q = (Param) new ObjectInputStream(in).readObject();

For high performance distributed computing inefficient serialization cannot be tolerated. Therefore, we've looked into the details of the official serialization, which is mostly implemented in Java itself, and derived an optimized replacement for it. In some benchmarks, we could eliminate 81-97% of the overhead caused by the regular Java serialization. For details please refer to the section "JavaParty papers".

Object Serialization vs. Fast Marshaling

The regular Java serialization is justifiable for persistent object storage, because it guarantees that objects can be reconstructed from their byte sequence representation even with future Java releases, and even with modified application classes. Our optimized serialization does not make such guarantees. Instead, it is designed for exchanging objects between running VMs that share the same class base.

Look and Feel

From the programmer's point of view our optimized serialization is slightly more difficult to use (you know, there is no free lunch.) The main difference is that instead of java.io.Serializable a newly introduced interface uka.transport.Transportable has to be implemented. In contrast to java.io.Serializable, the interface uka.transport.Transportable is not empty:

package uka.transport;

public interface Transportable
    extends java.io.Serializable, Cloneable 
{
    // *** object marshaling ***
    public void marshal(MarshalStream s) 
      throws java.io.IOException;

    // *** object unmarshaling ***
    // public Transportable(UnmarshalStream s) 
    //   throws java.io.IOException;

    public void unmarshalReferences(UnmarshalStream s) 
      throws java.io.IOException, ClassNotFoundException;

    // *** local object copy ***
    public Object deepClone(DeepClone _helper) 
      throws CloneNotSupportedException;
}

Each class whose objects should be marshaled efficiently must provide an implementation for the methods declared in the Transportable interface. Subclasses of a "transportable" class must override these methods, if they add fields to the base class. If a subclass does not add additional fields, it nevertheless must provide a constructor related to marshaling. For details see below.

Usage of the efficient serialization with transportable objects is almost identical to the regular Java serialization. Just replace java.io.OutputStream with uka.transport.MarshalStream and java.io.InputStream with uka.transport.UnmarshalStream. In the following example, please assume that class TParam implements interface uka.transport.Transportable.

// Assume: TParam p, InputStream in, OutputStream out
//
// Writing a transportable object into a stream and reading it back
new MarshalStream(out).writeObject(p);
TParam q = (TParam) new UnmarshalStream(in).readObject();

The following sections will explain how to efficiently implement the methods required by the interface uka.transport.Transportable. If you feel that it is unreasonable to write marshaling code for your classes, please have a look at the bottom of this page: Such marshaling code can be generated automatically.

Last modified 12 years ago Last modified on Aug 22, 2005 9:01:45 AM