Reviews : Java Books : JavaRMI :


Title: Java RMI
ISBN: 1-56592-452-5, Order Number: 4525
US Price: $39.95
© O'Reilly & Associates, Inc.

Using Serialization

Serialization is a mechanism built into the core Java libraries for writing a graph of objects into a stream of data. This stream of data can then be programmatically manipulated, and a deep copy of the objects can be made by reversing the process. This reversal is often called deserialization.

In particular, there are three main uses of serialization:

As a persistence mechanism
If the stream being used is FileOutputStream, then the data will automatically be written to a file.

As a copy mechanism
If the stream being used is ByteArrayOutputStream, then the data will be written to a byte array in memory. This byte array can then be used to create duplicates of the original objects.

As a communication mechanism
If the stream being used comes from a socket, then the data will automatically be sent over the wire to the receiving socket, at which point another program will decide what to do.

The important thing to note is that the use of serialization is independent of the serialization algorithm itself. If we have a serializable class, we can save it to a file or make a copy of it simply by changing the way we use the output of the serialization mechanism.

As you might expect, serialization is implemented using a pair of streams. Even though the code that underlies serialization is quite complex, the way you invoke it is designed to make serialization as transparent as possible to Java developers. To serialize an object, create an instance of ObjectOutputStream and call the writeObject( ) method; to read in a serialized object, create an instance of ObjectInputStream and call the readObject( ) object.

ObjectOutputStream

ObjectOutputStream, defined in the java.io package, is a stream that implements the "writing-out" part of the serialization algorithm.[2] The methods implemented by ObjectOutputStream can be grouped into three categories: methods that write information to the stream, methods used to control the stream's behavior, and methods used to customize the serialization algorithm.

The "write" methods

The first, and most intuitive, category consists of the "write" methods:

public void write(byte[] b); 
public void write(byte[] b, int off, int len); 
public void write(int data);
public void writeBoolean(boolean data); 
public void writeByte(int data); 
public void writeBytes(String data); 
public void writeChar(int data);
public void writeChars(String data); 
public void writeDouble(double data); 
public void writeFields(  ); 
public void writeFloat(float data); 
public void writeInt(int data); 
public void writeLong(long data); 
public void writeObject(Object obj);
public void writeShort(int data); 
public void writeUTF(String s);
public void defaultWriteObject(  );

For the most part, these methods should seem familiar. writeFloat( ), for example, works exactly as you would expect after reading Chapter 1--it takes a floating-point number and encodes the number as four bytes. There are, however, two new methods here: writeObject( ) and defaultWriteObject( ).

writeObject( ) serializes an object. In fact, writeObject( ) is often the instrument of the serialization mechanism itself. In the simplest and most common case, serializing an object involves doing two things: creating an ObjectOuptutStream and calling writeObject( ) with a single "top-level" instance. The following code snippet shows the entire process, storing an object--and all the objects to which it refers--into a file:

FileOutputStream underlyingStream = 
  	new FileOutputStream("C:\\temp\\test");
ObjectOutputStream serializer = 
	new ObjectOutputStream(underlyingStream);
serializer.writeObject(serializableObject);
Note:Color coded lines have been split for dislplay purposes.

Of course, this works seamlessly with the other methods for writing data. That is, if you wanted to write two floats, a String, and an object to a file, you could do so with the following code snippet:

FileOutputStream underlyingStream = 
	new FileOutputStream("C:\\temp\\test");
ObjectOutputStream serializer = 
	new ObjectOutputStream(underlyingStream);
serializer.writeFloat(firstFloat);
serializer.writeFloat(secongFloat);
serializer.writeUTF(aString);
serializer.writeObject(serializableObject);
Note:Color coded lines have been split for dislplay purposes.

TIP:   ObjectOutputStream's constructor takes an OutputStream as an argument. This is analagous to many of the streams we looked at in Chapter 1. ObjectOutputStream and ObjectInputStream are simply encoding and transformation layers. This enables RMI to send objects over the wire by opening a socket connection, associating the OutputStream with the socket connection, creating an ObjectOutputStream on top of the socket's OutputStream, and then calling writeObject( ).

The other new "write" method is defaultWriteObject(). defaultWriteObject( ) makes it much easier to customize how instances of a single class are serialized. However, defaultWriteObject( ) has some strange restrictions placed on when it can be called. Here's what the documentation says about defaultWriteObject( ):

Write the nonstatic and nontransient fields of the current class to this stream. This may only be called from the writeObject method of the class being serialized. It will throw the NotActiveException if it is called otherwise.

That is, defaultWriteObject( ) is a method that works only when it is called from another specific method at a particular time. Since defaultWriteObject( ) is useful only when you are customizing the information stored for a particular class, this turns out to be a reasonable restriction. We'll talk more about defaultWriteObject( ) later in the chapter, when we discuss how to make a class serializable.

The stream manipulation methods

ObjectOutputStream also implements four methods that deal with the basic mechanics of manipulating the stream:

public void reset(  );
public void close(  );
public void flush(  );
public void useProtocolVersion(int version); 

With the exception of useProtocolVersion( ), these methods should be familiar. In fact, reset( ), close( ), and flush( ) are standard stream methods. useProtocolVersion( ), on the other hand, changes the version of the serialization mechanism that is used. This is necessary because the serialization format and algorithm may need to change in a way that's not backwards-compatible. If another application needs to read in your serialized data, and the applications will be versioning independently (or running in different versions of the JVM), you may want to standardize on a protocol version.

TIP:   There are two versions of the serialization protocol currently defined: PROTOCOL_VERSION_1 and PROTOCOL_VERSION_2. If you send serialized data to a 1.1 (or earlier) JVM, you should probably use PROTOCOL_VERSION_1. The most common case of this involves applets. Most applets run in browsers over which the developer has no control. This means, in particular, that the JVM running the applet could be anything, from Java 1.0.2 through the latest JVM. Most servers, on the other hand, are written using JDK1.2.2 or later.[3] If you pass serialized objects between an applet and a server, you should specify the serialization protocol.



2. RMI actually uses a subclass of ObjectOutputStream to customize its behavior.

3. The main exception is EJB containers that require earlier versions of Java. At this writing, for example, Oracle 8i's EJB container uses JDK 1.1.6.

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.