Serialization FAQ From jGuru

72
Serialization FAQ From jGuru Generated Sep 13, 2005 1:11:57 PM What is object serialization? Serializing an object involves encoding its state in a structured way within a byte array. Once an object is serialized, the byte array can be manipulated in various ways; it can be written to a file, sent over a network using a socket-based connection or RMI, or persisted within a database as a BLOB. The serialization process encodes enough information about the object type within the byte stream, allowing the original object to be easily recreated upon deserialization, at a later point in time. How should I declare fields within my serializable class to prevent them from being serialized? Within JDK 1.1, any non-static field declared as transient is not serialized. (Static fields are not serialized anyway) Java 2 provides you with another mechanism for specifying which fields need to be serialized. Your class can declare the static field: public final ObjectStreamField[] serialPersistentFields = {...}; initialized with instances of ObjectStreamField, within each instance indicating the name and type of the serializable field. For example: public class FooBar implements Serialzable { private Foo foo; private int bar; private String passwd; public final static ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("foo",Foo.class), new ObjectStreamField("bar",Integer.TYPE) }; } indicates that only the fields foo and bar must be serialized. Can I persist my objects using serialization instead of using a relational or object database?

Transcript of Serialization FAQ From jGuru

Page 1: Serialization FAQ From jGuru

Serialization FAQ From jGuru Generated Sep 13, 2005 1:11:57 PM

What is object serialization?Serializing an object involves encoding its state in a structured way within a byte array. Once an object is serialized, the byte array can be manipulated in various ways; it can be written to a file, sent over a network using a socket-based connection or RMI, or persisted within a database as a BLOB.

The serialization process encodes enough information about the object type within the byte stream, allowing the original object to be easily recreated upon deserialization, at a later point in time.

How should I declare fields within my serializable class to prevent them from being serialized?Within JDK 1.1, any non-static field declared as transient is not serialized. (Static fields are not serialized anyway)

Java 2 provides you with another mechanism for specifying which fields need to be serialized. Your class can declare the static field:

public final ObjectStreamField[] serialPersistentFields = {...};

initialized with instances of ObjectStreamField, within each instance indicating the name and type of the serializable field.

For example:

public class FooBar implements Serialzable { private Foo foo; private int bar; private String passwd;

public final static ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("foo",Foo.class), new ObjectStreamField("bar",Integer.TYPE) };}

indicates that only the fields foo and bar must be serialized.

Can I persist my objects using serialization instead of using a relational or object database?No. While serialization is a highly versatile mechanism having numerous applications, your long term storage needs should continue to be addressed by conventional relational or object databases.

Note that serialization does not provide any features for transaction management and concurrency control. Nor does it provide typical database features like indexed access, caching and a query language.

Page 2: Serialization FAQ From jGuru

Why am I having an InvalidClassException thrown during the serialization of my object which implements the Externalizable interface?Unlike objects which implement the Serializable interface, it is mandatory for objects implementing the Externalizable interface to also implement a public no-arg constructor. This constructor is the very first thing that is invoked by readExternal() when reconstructing the object from the bytestream. If a public no-arg constructor is absent, then an InvalidClassException is immediately thrown.

Why doesn't serialization save the value of static variables?Variables declared as static members are not considered part of the state of an object because they are shared by all instances of that class. Classes which need to preserve the value of static members during serialization should save and restore these values explicitly using private void readObject(ObjectInputStream) and private void writeObject(ObjectOutputStream).

How can I speed up serialization?One thing that slows serialization down considerably is the calculation of the serial version unique identifier, or SUID. This value needs to be calculated when an object is written out, because ObjectOutputStream includes it in the serialized version of the object. It also needs to be calculated when an object is read in, because ObjectInputStream needs to compare the SUID of the serialized object to the SUID of the class file to ensure version compatibility.

You can turn off this calculation by explicitly defining an SUID in your class. The SUID must be defined as:

private static final long serialVersionUID = nnnL;

where "nnn" represents a long integer. To ensure backward compatibility with existing serialized objects of that class, you cannot choose an arbitrary long integer here; you must choose the same value that was automatically generated. You can find out what that was by running the Java 2 SDK tool "serialver" on your old class file.

Comments and alternative answers

This Is A Myth Author: Daniel Gredler (http://www.jguru.com/guru/viewbio.jsp?EID=1179237), Jun 16, 2004This is a prevalent Java serialization myth: that you can speed serialization up by hard-coding a SUID. The calculated SUID gets cached, so you only incur the overhead (max 50ms) once. Or maybe more, since they're cached using soft references, but you get the idea. See http://www.javaworld.com/javaworld/javaqa/2003-06/02-qa-0627-mythser.html? for more details.

Page 3: Serialization FAQ From jGuru

What is the Stream Unique IDentifier (SUID) that is written out as part of the serial stream?Location: http://www.jguru.com/faq/view.jsp?EID=5060 Created: Jan 15, 2000 Author: Govind Seshadri (http://www.jguru.com/guru/viewbio.jsp?EID=14)

The serialization process uses a unique identification value to keep track of the persisted objects. When a Serializable or Externalizable object is saved, it's fully-qualified class name and the Stream Unique IDentifier (SUID) of the class is written out to the stream. The SUID is a unique 64-bit hash, and is obtained by applying the SHA-1 message digest algorithm to the serialized class, including its name, field types and method signatures.

This step is important as it prevents the data persisted by one class from being read by another class with the same name. For any class to be able to read successfully from an object stream, it is imperative that its SUID matches the SUID of the serialized data in the stream.

What is the purpose of the tool "serialver"? How is it used?Location: http://www.jguru.com/faq/view.jsp?EID=5063 Created: Jan 15, 2000 Author: Govind Seshadri (http://www.jguru.com/guru/viewbio.jsp?EID=14)

When an object is serialized, its fully qualified class name, as well as the 64-bit SUID, is written to the stream. Later, when a class attempts to read the serialized object, it is important that its SUID matches that of the serialized object, as otherwise an InvalidClassException is thrown.

But therein lies the problem - because, when classes evolve, so do their SUIDs. But luckily, there is a solution at hand in the form of serialver - a utility provided by the Java SDK, which allows us to generate the SUID of a Java class file. If the output of serialver is included within a class file, then that class is now compatible with all it's persisted objects and can be used to read back the same, even though the class definition itself may undergo some mutation down the road.

For instance, running:

serialver foo.Person

generates:

foo.Person: static final long serialVersionUID =3734178553292263588L;

Now, you can continue to read the foo.Person objects even with future versions of the class, as long as they have the "old" SUID embedded within them as:

static final long serialVersionUID =3734178553292263588L;

This will work because a class, before it reads the serialized data from the stream, first checks for the presence of the serialVersionUID field within. If found, its value is written to the stream, instead of one being calculated on the fly. Since the SUID values should now match, there would be no problem in reading in the serialized data.

Page 4: Serialization FAQ From jGuru

It is probably easier to use a GUI version of serialver, which can be enabled by the -show option.

Comments and alternative answers

serialver x? Author: Eric Freiborg (http://www.jguru.com/guru/viewbio.jsp?EID=933773), Jul 1, 2002Is the parameter passed into serialver the class being serialized (x.class or x.java) or is it the serialized file of that class(x.ser)? Thanks, Eric

Re: serialver x? Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10), Jul 1, 2002The argument is the class name. serialver uses the standard Java classloader to search for the class file definition (with file extension .class) in your classpath. The class file definition can be in a jar file as well, as long as that jar file is in your classpath. Try this, for example, to print out the SUID for one of the core JDK classes: serialver java.lang.String

serialver should never really be needed. Author: Richard Martin (http://www.jguru.com/guru/viewbio.jsp?EID=1051951), Jan 30, 2003

The Serialization spec does not mandate that the serialVersionUID declared in the class be any particular value.

If you are creating new class, you can declare it with a serialVersionUID of anything your like.

As far as I can tell the only reason you would ever want to use serialver is if an earlier version of the class did not declare a serialVersionUID and you then want to make a serial-compatible change to that class. Then you would run serialver on the old class and declare that value in your new class. You then stick with that value until you make a serial-incompatible change, at which point you can use an number you like (obviously different from the original number).

If you follow the practise of declaring a serialVersionUID in every serializable class, you would never need to use serialver.

What changes are considered serial-compatible? Author: Eric Rizzo (http://www.jguru.com/guru/viewbio.jsp?EID=10628), Jun 24, 2003

Page 5: Serialization FAQ From jGuru

As stated above, it is good practice to declare your own serialVersionUID for all your serializable classes. This allows you to make serial-compatible changes to the class without getting InvalidClassException. But where does the Java spec define exactly what are considered serial-compatible changes and what are not? A link would be appreciated.

Re: What changes are considered serial-compatible? Author: Dimas Moreira Junior (http://www.jguru.com/guru/viewbio.jsp?EID=1104012), Jul 25, 2003

The Java Object Serialization Specification specifies which changes are serial-compatible.

What are the compatible and incompatible changes when dealing with versioned serialized objects?Location: http://www.jguru.com/faq/view.jsp?EID=5064 Created: Jan 15, 2000 Author: Govind Seshadri (http://www.jguru.com/guru/viewbio.jsp?EID=14)

If a newer version of a serialized object has to be compatible with an older version, it is important that the newer version abides by the rules for compatible and incompatible changes.

A compatible change is one that can be made to a new version of the class, which still keeps the stream compatible with older versions of the class. Examples of compatible changes are:

Addition of new fields or classes does not affect serialization, as any new data in the stream is simply ignored by older versions. When the instance of an older version of the class is deserialized, the newly added field will be set to its default value.

You can field change access modifiers like private, public, protected or package as they are not reflected to the serial stream.

You can change a transient or static field to a non-transient or non-static field, as it is similar to adding a field.

You can change the access modifiers for constructors and methods of the class. For instance a previously private method can now be made public, an instance method can be changed to static, etc. The only exception is that you cannot change the default signatures for readObject() and writeObject() if you are implementing custom serialization. The serialization process looks at only instance data, and not the methods of a class.

Changes which would render the stream incompatible are:

Once a class implements the Serializable interface, you cannot later make it implement the Externalizable interface, since this will result in the creation of an incompatible stream.

Deleting fields can cause a problem. Now, when the object is serialized, an earlier version of the class would set the old field to its default value since nothing was available within the stream. Consequently, this default data may lead the newly created object to assume an invalid state.

Page 6: Serialization FAQ From jGuru

Changing a non-static into static or non-transient into transient is not permitted as it is equivalent to deleting fields.

You also cannot change the field types within a class, as this would cause a failure when attempting to read in the original field into the new field.

You cannot alter the position of the class in the class hierarchy. Since the fully-qualified class name is written as part of the bytestream, this change will result in the creation of an incompatible stream.

You cannot change the name of the class or the package it belongs to, as that information is written to the stream during serialization.

Comments and alternative answers

Do the rules for compatible changes require that the... Author: Michael Prescott (http://www.jguru.com/guru/viewbio.jsp?EID=25013), May 29, 2000Do the rules for compatible changes require that the class versions also have the same serialVersionUID, or does having the same serialVersionUID allow you to enforce compatability when these rules are violated?

Can't refactor Author: Alex Chaffee (http://www.jguru.com/guru/viewbio.jsp?EID=3), Aug 15, 2002In addition to not being able to change the package or name of the class, I believe it is impossible to change the names of serialized fields. Since "rename" is one of the most basic and useful refactorings, this is a big problem.

What are the advantages and disadvantags of serialization?Location: http://www.jguru.com/faq/view.jsp?EID=5068 Created: Jan 15, 2000 Author: Govind Seshadri (http://www.jguru.com/guru/viewbio.jsp?EID=14)

The advantages of serialization are: It is easy to use and can be customized. The serialized stream can be encrypted, authenticated and compressed,

supporting the needs of secure Java computing. Serialized classes can support coherent versioning and are flexible enough to

allow gradual evolution of your application's object schema. Serialization can also be used as a mechanism for exchanging objects

between Java and C++ libraries, using third party vendor libraries (like RogueWave's Tools.h++ ) within C++.

There are simply too many critical technologies that rely upon serialization, including RMI, JavaBeans and EJB.

However, serialization has some disadvantages too:

It should ideally not be used with large-sized objects, as it offers significant overhead. Large objects also significantly increase the memory requirements of your application since the object input/output streams cache live references to all objects written to or read from the stream until the stream is closed or reset. Consequently, the garbage collection of these objects can be inordinately delayed.

Page 7: Serialization FAQ From jGuru

The Serializable interface does not offer fine-grained control over object access - although you can somewhat circumvent this issue by implementing the complex Externalizable interface, instead.

Since serialization does not offer any transaction control mechanisms per se, it is not suitable for use within applications needing concurrent access without making use of additional APIs.

Comments and alternative answers

Regarding serialization Author: Ravishankar CS (http://www.jguru.com/guru/viewbio.jsp?EID=534441), Mar 21, 2002Hello, you have mentioned that one of the advantages of serialization is that it can be customized,compressed etc. can u please elaborate on the above 2 points thanking you, Ravishankar

Re: Regarding serialization Author: venugopal vasireddy (http://www.jguru.com/guru/viewbio.jsp?EID=828472), Apr 7, 2002Using Externalizable interfaces you can plug in your own algorithms (compress technics,encription, etc)

Does serialization depend on the browser, platform, or VM?Location: http://www.jguru.com/faq/view.jsp?EID=5293 Created: Jan 17, 2000 Modified: 2000-01-17 13:43:08.766Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

The serialization format is independent of browser, independent of JVM vendor, and independent of platform. So serialization should work with any combination of the above.

For example, a serialized object written by Windows can be read by Unix, and vice verse. This is generally true of all I/O in Java.

Comments and alternative answers

You did not make any comment regarding different v... Author: Mathew Brozowski (http://www.jguru.com/guru/viewbio.jsp?EID=5786), Jan 20, 2000You did not make any comment regarding different versions of the JVM. Can a 1.2 server-side Java application serialize an object to an applet in a browser that has a built-in 1.1 version JVM?

Compatibility between Java versions is discussed in... Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10), Feb 10, 2000Compatibility between Java versions is discussed in the FAQ found at http://www.jguru.com/jguru/faq/view.jsp?EID=13165

Page 8: Serialization FAQ From jGuru

Can I use a BufferedOutputStream with an ObjectOutputStream to serialize an object?Location: http://www.jguru.com/faq/view.jsp?EID=5295 Created: Jan 17, 2000 Modified: 2000-03-13 21:50:27.046Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Yes. In fact, it is recommended that you buffer all your input and output unless you have a good reason not to.

Here's an example of how to do this:

... String myobject = new String("myobject"); FileOutputStream file = new FileOutputStream("myobject.ser"); BufferedOutputStream bout = new BufferedOutputStream(file); ObjectOutputStream out = new ObjectOutputStream(bout); out.writeObject(myobject); out.flush(); ...

Java allows you to chain I/O streams together. Using a BufferedOutputStream makes output much more efficient because the I/O overhead is then expended on large chunks of data, rather than on individual bytes.

Likewise, many times it makes sense to compress your output, say if you are writing many large objects to a file or a socket. You can do this using a ZipOutputStream or a GZIPOutputStream in place of (or in addition to!) the BufferedOutputStream in the above example.

How can I validate what I've just deserialized?Location: http://www.jguru.com/faq/view.jsp?EID=7476 Created: Jan 22, 2000 Modified: 2000-02-02 10:43:46.655Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

When an object is deserialized, its internal state is restored to what it was at the time of serialization. So if you serialized a good object, you will get a good object back or an exception will be thrown.

However, there are times when you need to check more than just the state of the object. Take for example an object that represents a credit card, including cardholder name, credit card number, and expiration date. If this credit card is deserialized after its expiration date, then although its state is intact, the card is no longer valid and can't be used in a purchase transaction. This sort of information may be checked in the serializable object's readObject() method.

Because serialization saves and restores complete object graphs, you might also imagine there is a need to validate consistency of the entire graph. This cannot be done within a single object's readObject() method - it can only be done after all the objects in the graph are restored.

To validate an entire graph, you need to do two things:

Page 9: Serialization FAQ From jGuru

provide an object which implements the java.io.ObjectInputValidation interface

register this object with the ObjectInputStream which is reading the graph

The java.io.ObjectInputValidation interface defines just the method validateObject() which is declared to throw an InvalidObjectException. Your validator object must provide an implementation for this method which checks the validity of the graph and throws this exception when needed.

The validator object must be registered with the stream during the read of the graph; this is usually done within a readObject() method by invoking the registerValidation() method on the ObjectInputStream, passing the stream a reference to the validator object.

Here is a short example which shows the mechanics of validation and demonstrates that the validation occurs after the object graph has been reconstituted. This simple example stores objects of type Validate in a collection, and validates upon deserialization that the collection is homogeneous.

import java.io.*;import java.util.*;

public class Validate implements Serializable, ObjectInputValidation {

Vector collection;

public Validate(Vector collection) { this.collection = collection; }

private void readObject(ObjectInputStream in) throws OptionalDataException, ClassNotFoundException, IOException { System.out.println("reading object"); in.registerValidation(this, 0); in.defaultReadObject(); }

private void writeObject(ObjectOutputStream out) throws IOException { System.out.println("writing object"); out.defaultWriteObject(); }

public void validateObject() throws InvalidObjectException { System.out.println("validating object"); Enumeration e = collection.elements(); while (e.hasMoreElements()) { if (!(e.nextElement() instanceof Validate)) throw new InvalidObjectException("Not a homeogeneous collection!"); } }

public static void main(String[] args)

Page 10: Serialization FAQ From jGuru

throws IOException, ClassNotFoundException { Vector collection = new Vector(); for (int i=0; i<10; i++) { Validate obj = new Validate(collection); collection.addElement(obj); } ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("validate.ser")); out.writeObject(collection); out.flush(); out.close(); ObjectInputStream in = new ObjectInputStream( new FileInputStream("validate.ser")); try { Vector restored = (Vector) in.readObject(); } catch (InvalidObjectException e) { System.out.println("invalid collection!"); } }}Comments and alternative answers

Example Validation Code is "Superfluous" Author: Tony LaPaso (http://www.jguru.com/guru/viewbio.jsp?EID=2330), Dec 2, 2001

Generally, it seems to me the validation mechanism in the Serialization API is pretty much useless -- and the example code I think illustrates this. But maybe I'm wrong...

Anyway, the validation performed in the sample code gets executed for each and ever Validate object that gets deserialized. In other words, you can perform the exact same validation at the end of each readObject() method and the effect is that same.

To prove the point, I've added a few print statements to the original code to show when and for which objects the validation code is executed. Here is the original code with the added print statements:

import java.io.*;import java.util.*;

public class Validate implements Serializable, ObjectInputValidation {

Vector collection;

public Validate(Vector collection) { this.collection = collection; }

Page 11: Serialization FAQ From jGuru

private void readObject(ObjectInputStream in) throws OptionalDataException, ClassNotFoundException, IOException { System.out.println("reading object"); in.registerValidation(this, 0); in.defaultReadObject(); System.out.println("FINISHED reading object for object " + hashCode()); }

private void writeObject(ObjectOutputStream out) throws IOException { System.out.println("writing object for object " + hashCode()); out.defaultWriteObject(); }

public void validateObject() throws InvalidObjectException { System.out.println("validating object for " + hashCode()); Enumeration e = collection.elements(); while (e.hasMoreElements()) { if (!(e.nextElement() instanceof Validate)) throw new InvalidObjectException("Not a homeogeneous collection!"); } }

public static void main(String[] args) throws IOException, ClassNotFoundException { Vector collection = new Vector(); for (int i=0; i<10; i++) { Validate obj = new Validate(collection); System.out.println("created new Validate object " + obj.hashCode()); collection.addElement(obj); } ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("validate.ser")); out.writeObject(collection); out.flush(); out.close(); ObjectInputStream in = new ObjectInputStream( new FileInputStream("validate.ser")); try { Vector restored = (Vector) in.readObject(); } catch (InvalidObjectException e) { System.out.println("invalid collection!"); } }}

I would like to see an example of where the validateObject() method really adds value. In every situation I've seen, however, the code in the validateObject()

Page 12: Serialization FAQ From jGuru

method could be moved to the end of the readObject() an dthe effect would be the same, but more elegane (IMHO).

Can someone provide an example of where validateObject() is really necessary??

Re: Example Validation Code is "Superfluous" Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7), Mar 11, 2002It is called subclassing. When you subclass, the parent classes validator is called at the end of the child class being initialized, not the parent class.

Re: Example Validation Code is "Superfluous" Author: Carl van Denzen (http://www.jguru.com/guru/viewbio.jsp?EID=1138694), Jan 13, 2004I tried to use the ObjectValidation to restore a static BitSet after restoring an ArrayList.The ArrayList contains objects that contain a unique id number. To track which id numbers are still free I use a BitSet.At the end I couldn't figure out how to register with the stream and I gave up. My solution: after the readObject call, I simply call my validateObject method "manually" and that just works fine.The code looks something like this: class Players extends ArrayList { public Players(String name) { this.name=name; // I do not know the method name getFirstClear usedIdNrs.set(usedIdNrs.getFirstClear()); } BitSet usedIdNrs; static { usedIdNrs.set(0); // skip player number 0 } validateObject() { usedIdNrs.set(0); // do not use number 0 for (i=0;i<size();i++) usedIdNrs.set(get(i).idNr)); }} // end of class

main players=in.readObject(); players.validateObject;

What resources are available to read Java serialized output in C++ programs?Location: http://www.jguru.com/faq/view.jsp?EID=10361 Created: Jan 31, 2000 Modified: 2000-01-31 09:37:28.249Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question

Page 13: Serialization FAQ From jGuru

originally posed by John Zukowski PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=7

Tools.h++ Professional by RogueWave http://www.roguewave.com/products/toolspro/

Can an application running in a version 1.1.x JVM read an object that was serialized by an application running in a version 1.2.x JVM?Location: http://www.jguru.com/faq/view.jsp?EID=13165 Created: Feb 10, 2000 Modified: 2000-05-15 19:46:28.884Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Changes were made to the default serialization stream format between version 1.1.x and version 1.2.x of the JDK. As a result, if you are writing objects with one version and reading them with another you may have to take special steps to ensure compatibility.

There are two distinct forms of the serialization protocol used. These protocol versions are identified by constants in the ObjectStreamConstants class:

ObjectStreamConstants.PROTOCOL_VERSION_1 ObjectStreamConstants.PROTOCOL_VERSION_2

The protocol version that is actually used during serialization is determined as follows:

JDK 1.1.x defaults to writing using PROTOCOL_VERSION_1 JDK 1.2.x defaults to writing using PROTOCOL_VERSION_2 JDK 1.1.7 and higher can read both protocol versions

Thus, if both applications use JDK 1.1.7 or higher, the serialization/deserialization will be successful.

Applications using JDK version 1.2 and higher may override the default serialization protocol used for writing objects by invoking the useProtocolVersion(int) method on their ObjectOutputStream, where the integer argument is one of the two constants shown above. Setting the protocol version to PROTOCOL_VERSION_1 ensures compatibility with all versions of Java when needed.

What is UTF that Serialization uses to write strings?Location: http://www.jguru.com/faq/view.jsp?EID=14685 Created: Feb 15, 2000 Modified: 2000-02-15 22:24:49.342Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by John Zukowski PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=7

The Java programming language was designed from the ground up to be compatible with multiple character sets from multiple languages. This entails using a non-ASCII character and string representation within the language itself.

Internally, Java stores and manipulates all characters and strings as Unicode. Externally, in serialization and in bytecode, Java uses the UTF-8 encoding of the Unicode character set. For each character, UTF-8 encoding is a 1-, 2-, or 3-byte

Page 14: Serialization FAQ From jGuru

representation of the corresponding 2-byte Unicode character (ASCII characters are encoded as 1 byte, non-ASCII characters are encoded as 2 or 3 bytes).

UTF-8 has the property that the ASCII characters 0x20-0x7E encode to UTF-8 1-byte characters of the same value. Therefore, UTF-8 is 100% compatible with existing systems which use ASCII encoding. This is one of the main reasons UTF-8 was chosen for Java's external character representation - it allows complete compatibility with ASCII as well as allowing for a wide range of international characters.

For more information, refer to the FAQ What is Unicode?

How do I load a serialized applet?Location: http://www.jguru.com/faq/view.jsp?EID=17878 Created: Feb 24, 2000 Modified: 2002-04-30 06:57:05.197Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7)

Instead of specifying the CODE attribute of an <APPLET> tag, you use the OBJECT attribute, as in: <APPLET OBJECT=TheApplet.ser WIDTH=300 HEIGHT=300></APPLET>

This allows you to preinitialize your applet to some saved state, instead of having to reinitialize your applet each time it is loaded.

Support for this in browsers is severly limited. Don't rely on it.

I want to have complete control of the binary file format generated by ObjectOutputStream, so I implemented Externalizable in my objects and extended ObjectOutputStream so that I could overwrite the writeStreamHeader() and readStreamHeader() methods. But still when I write data to the stream, some extra information is written. How can I prevent this?Location: http://www.jguru.com/faq/view.jsp?EID=21746 Created: Mar 8, 2000 Modified: 2000-03-08 10:02:53.722Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Radhesh Mohandas (http://www.jguru.com/guru/viewbio.jsp?EID=12979

A serialized object is written out by an ObjectOutputStream and read in by an ObjectInputStream. It is these streams that are responsible for writing and recognizing the binary serialization format. Objects that implement Serializable or Externalizable can only tell the underlying stream what data they want to write out - they don't have control over the binary format.

These object streams do allow minimal customization of the protocol. Namely, the ability to override writeStreamHeader() and readStreamHeader() in subclasses. This affects only the magic number and version number written at the beginning of the serialized data, not the internal structure of the data itself. To do any more customization requires you to write your own stream classes.

Page 15: Serialization FAQ From jGuru

This is true even for primitive types written out through the ObjectOutputStream, because ObjectOutputStream implements its own write() methods to conform to the serialization protocol.

As an example, here is a snippet of code which writes out one byte to an ObjectOutputStream:

...FileOutputStream file = new FileOutputStream("test.ser");ObjectOutputStream out = new ObjectOutputStream(file);out.write(65);out.flush();out.close();...The resulting file, "test.ser", will have a total length of 7 bytes, as follows: 0xACED // ObjectStreamContents.STREAM_MAGIC0x0005 // ObjectStreamContents.STREAM_VERSION0x77 // ObjectStreamContents.TC_BLOCKDATA0x01 // length of data0x41 // 65 decimal

Subclassing ObjectOutputStream and overriding writeStreamHeader() will allow you to change, delete, or add to the first 4 bytes shown above, but that is the limit of customization allowed by overriding. In particular, the block header TC_BLOCKDATA is written by a private method within ObjectOutputStream, so it can't be overridden.

There is a lot of logic behind the serialization protocol. From the above example, you see that the protocol writes out an indicator that a block of data follows, then writes out the length of the data, and finally the data itself. This allows efficient reading of the data by a stream, and accomodates variable-length data structures. If you really want to define your own protocol, you will have to write your own input and output stream classes that that use your own binary format. You will then need to use these in place of ObjectInputStream and ObjectOutputStream. You will probably want to implement Externalizable in all your classes as well, so you can control how each object writes its own state.

Using ObjectOutputStream, how can I use writeObject() to write the same object twice, so on the other end readObject() will read two separate objects, not two references to the same object?Location: http://www.jguru.com/faq/view.jsp?EID=25970 Created: Mar 19, 2000 Modified: 2000-03-19 15:28:45.871Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Michael Prescott (http://www.jguru.com/guru/viewbio.jsp?EID=25013

Java's serialization mechanism keeps track of which objects were written to an ObjectOutputStream; when an object is written for the second time a object handle is sent in place of the actual object. This makes the serialization protocol more efficient and allows circular references to be properly dealt with.

This algorithm poses a problem if you send an object, make a change to that object, then try to send it again; the receiving end will not read the changed object, it will reconstruct the original object using the object handle.

Page 16: Serialization FAQ From jGuru

You can tell the ObjectOutputStream to "forget" about previously serialized objects by invoking the reset() method. Resetting the stream causes the stream to behave as if it were just constructed, without any knowledge of what was written to the stream prior to the reset(). You should use this method only when required, otherwise you will end up serializing far more data than necessary.

If an object is serialized by a 1.1.x VM, can it be de-serialized by a 1.2.x VM?Location: http://www.jguru.com/faq/view.jsp?EID=28497 Created: Mar 25, 2000 Modified: 2000-03-25 12:33:24.984Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Eric Rath (http://www.jguru.com/guru/viewbio.jsp?EID=26650

Yes. No special steps are needed for this to work.

When trying to serialize large strings, or pass large strings as parameters to remote methods, I keep getting a java.io.EOFException. This only happens for strings, not for other large objects. What is the problem?Location: http://www.jguru.com/faq/view.jsp?EID=28687 Created: Mar 26, 2000 Modified: 2001-05-22 08:35:41.241Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

In Java versions prior to 1.3, there is a limit of 64kB on the size of a serialized String object. This is because ObjectOutputStream delegates String serialization to an instance of DataOutputStream, which writes out the length of a string as a 16-bit short, followed by the UTF-8 encoded string. The 64kB limit is due to the maximum value a short datatype can hold. A UTFDataFormatException will be thrown if you try to serialize a String greater than 64kB in these versions of the JDK.

This restriction has been removed by implementation changes in Java 2 SDK versions 1.3 and later. If you attempt to deserialize a String larger than 64kB in a pre-1.3 JVM you will get a StreamCorruptedException.

Are there any system properties in Java that affect Serialization?Location: http://www.jguru.com/faq/view.jsp?EID=28694 Created: Mar 26, 2000 Modified: 2000-03-26 12:08:01.108Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

No.Comments and alternative answers

There are some Java Security settings that do affect serializaton, however. Author: Dave Masser-Frye (http://www.jguru.com/guru/viewbio.jsp?EID=939347), Jul 5, 2002According to the Object Serialization Specification, If the subclass of ObjectInputStream is not considered part of the system domain, a line has to be added to the security policy file to provide to a subclass of ObjectInputStream permission to call enableResolveObject. The SerializablePermission to add is "enableSubstitution". AccessControlException is thrown if the protection domain of the subclass of ObjectStreamClass does not have

Page 17: Serialization FAQ From jGuru

permission to "enableSubstitution" by calling enableResolveObject. See the document JavaTM Security Architecture (JDKTM 1.2) for additional information about the security model.

While this is not technically a property, it is a configuration that must be addressed in rare circumstances.

I keep getting an InvalidClassException when I read in my serialized objects. What am I doing wrong? Location: http://www.jguru.com/faq/view.jsp?EID=28705 Created: Mar 26, 2000 Modified: 2000-03-26 22:54:31.294Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

An InvalidClassException is thrown if the serial version of the object read from the stream does not match that of the loaded class. What probably happened is you changed your class definition since the time you wrote out the serialized instance.

To find out how to fix this, see the FAQ at http://www.jguru.com/jguru/faq/view.jsp?EID=5063.

Is there a maximum size of a serialized object tree graph?Location: http://www.jguru.com/faq/view.jsp?EID=28713 Created: Mar 26, 2000 Modified: 2000-03-26 20:15:32.955Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by John Zukowski PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=7

There are limits, but it's difficult to quantify most of them. For example, the JVM stack size affects the graph serialization, since the tree walking is done depth-first, recursively. (This is called post-order traversal.) Too deep a recursion causes stack overflow. This limit can kick in for data structures on the order of 1000 deep, regardless of the size of the objects.

Other, less restrictive limits are that the object handle assigned to each object in a graph is an int, so there is a (rather large) limit on the number of objects in a graph. Likewise, the JVM places a limit on the number of members in an class, so objects have a limit on their size.

I think the only practical limit you are likely to encounter is the stack size. This can be avoided by customizing serialization with your own structure-specific readObject() and writeObject() methods.

Comments and alternative answers

Passing org.w3c.dom.Document via RMI Author: Kenson ODonald (http://www.jguru.com/guru/viewbio.jsp?EID=1003132), Sep 23, 2002In encountered the following problem recently. Is this related to the limitation?

Page 18: Serialization FAQ From jGuru

I got the output by catching a StackOverFlowError. The RMI call looked something like this:

rmiApp.pocessDoc(Document doc);

How can I get arround this problem? Thanks in advance.

java.rmi.MarshalException: error marshalling arguments; nested exception is: java.net.SocketException: Connection aborted by peer: socket write error java.net.SocketException: Connection aborted by peer: socket write error at java.net.SocketOutputStream.socketWrite(Native Method) at java.net.SocketOutputStream.write(SocketOutputStream.java:83) at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:72 ) at java.io.BufferedOutputStream.write(BufferedOutputStream.java:116) at java.io.ObjectOutputStream.drain(ObjectOutputStream.java:1463) at java.io.ObjectOutputStream.setBlockData(ObjectOutputStream.java:1486) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:407) at sun.rmi.server.UnicastRef.marshalValue(UnicastRef.java:268) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:106) at com.paetec.oss.bridge.revchain.PTCBridgeRevChainApp_Stub.processServi ceOrderDoc(PTCBridgeRevChainApp_Stub.java:96) at com.paetec.oss.bridge.revchain.PTCBridgeRevChainRmiClient.main(PTCBri dgeRevChainRmiClient.java:313)

Can I use an arbitrary long value for serialVersionUID when I declare it in my class?Location: http://www.jguru.com/faq/view.jsp?EID=28715 Created: Mar 26, 2000 Modified: 2000-03-26 15:24:31.6Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

If you don't have any previously serialized objects of that class around, you can initialize serialVersionUID to any long value you want. However, if you do have older versions of your class and wish to maintain backward compatibility, you must use the value of serialVersionUID that is determined for you by the serialver command. See http://www.jguru.com/jguru/faq/view.jsp?EID=5063 for more information on serialver.

How do I handle versioning of my Externalizable classes? Do I have to write a version number to the stream?Location: http://www.jguru.com/faq/view.jsp?EID=30732 Created: Mar 31, 2000 Modified: 2000-03-31 14:01:00.132Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Just as with classes that implement Serializable, the serialVersionUID field is checked when reading in Externalizable objects via an ObjectInputStream. If

Page 19: Serialization FAQ From jGuru

serialVersionUID is not explicitly defined in your Externalizable class, then one will be computed for you upon deserialization. See the FAQ at http://www.jguru.com/jguru/faq/view.jsp?EID=5063 for more details.

How do I use the @serial javadoc tag?Location: http://www.jguru.com/faq/view.jsp?EID=30794 Created: Mar 31, 2000 Modified: 2000-03-31 22:38:18.913Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

The @serial javadoc tag is used to document the meaning and acceptable values of serialized fields. It appears in a javadoc comment just prior to a field declaration, and is followed by a free-form field description, which may span more than one line. In the standard javadoc output, this information is displayed only in the "Serialized Form" page for that class.

If this serializable field has been added since the initial version of the class, the @since tag should also be used to help document the version changes in the serialized form.

How do I use the @serialData javadoc tag?Location: http://www.jguru.com/faq/view.jsp?EID=30795 Created: Mar 31, 2000 Modified: 2000-03-31 22:38:56.837Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

The @serialData javadoc tag is used to document methods which generate a serialization format other than the default. In particular, @serialData is typically used to document the writeExternal() method of Externalizable class es and the writeObject method of Serializable classes. It is followed by a free-form description of the data sent to the serialization stream; this should include the order, type, and description of the data. The data description may span more than one line, and may include HTML tags.

What things are required for a class that implements Externalizable?Location: http://www.jguru.com/faq/view.jsp?EID=31433 Created: Apr 3, 2000 Modified: 2000-04-03 10:18:13.694Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

A class that implements Externalizable must also: Have a public, no-argument constructor. Provide a writeExternal(ObjectOutput) method to save the state of the

object, including the state of any superclass, to the ObjectOutput stream. Provide a readExternal(ObjectInput) method to restore the state of the

object, including the state of any superclass, from the ObjectInput stream.

What things are required for a class that implements Serializable?Location: http://www.jguru.com/faq/view.jsp?EID=31434 Created: Apr 3, 2000 Modified: 2000-04-03 22:48:00.577Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Page 20: Serialization FAQ From jGuru

A class that implements Serializable must also: Have access to a no-argument constructor in its first non-serializable

superclass Identify non-serializable data members using the transient keyword or

explicitly mark data members as serializable using the serialPersistentFields member.

I'm having trouble getting Externalizable to work. Can you give a simple code example?Location: http://www.jguru.com/faq/view.jsp?EID=32108 Created: Apr 4, 2000 Modified: 2000-04-04 12:07:30.157Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Rama Turaga (http://www.jguru.com/guru/viewbio.jsp?EID=30127

The following code defines a simple Externalizable class that provides a main() method which instantiates an object, writes it to a file, restores it, then verifies that the restored object contains the same values as the original.

import java.io.*;import java.util.*;

/** * This program demonstrates how to write an Externalizable class */public class TestExternal implements Externalizable {

private String comment = "A serializable data member"; private Vector collection;

/** * A no-argument constructor is required for an Externalizable class */ public TestExternal() { this(null); }

public TestExternal(Vector collection) { this.collection = collection; }

/** * This method is responsible for saving the * entire state of the object */ public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(comment); // // You could also just do out.writeObject(collection) below, // but I prefer to loop over the contents and write them one // at a time. // out.writeInt(collection.size()); Enumeration e = collection.elements(); while (e.hasMoreElements()) {

Page 21: Serialization FAQ From jGuru

out.writeObject(e.nextElement()); } }

/** * This method is responsible for restoring the * entire state of the object */ public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException { // // What was written in writeExternal() must be read back here. // comment = (String) in.readObject(); int size = in.readInt(); collection = new Vector(size); for (int i=0; i<size; i++) { collection.addElement(in.readObject()); } }

/** * Delegates equality check to the objects stored within * this instance */ public boolean equals(Object o) { if (o instanceof TestExternal) { TestExternal other = (TestExternal) o; if (comment.equals(other.comment) && collection.size() == other.collection.size() ) { for (int i=0; i<collection.size(); i++) { if (!collection.elementAt(i).equals(other.collection.elementAt(i))) return false; } return true; } } return false; }

public static void main(String[] args) throws IOException, ClassNotFoundException { // // Create the data to store in this object, // then create and fill the object // Vector bunchOfIntegers = new Vector(); for (int i=0; i<10; i++) { Integer obj = new Integer(i); bunchOfIntegers.addElement(obj); } TestExternal original = new TestExternal(bunchOfIntegers);

// // Write the object to a file //

Page 22: Serialization FAQ From jGuru

ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("testexternal.ser")); out.writeObject(original); out.flush(); out.close();

// // Now read the object back in from the file // ObjectInputStream in = new ObjectInputStream( new FileInputStream("testexternal.ser")); TestExternal restored = (TestExternal) in.readObject();

// // Compare original object with restored object to // check that they are the same // if (restored.equals(original)) { System.out.println("The original is the same as the restored"); } else { System.out.println("There was a problem with Externalization:"); System.out.println("\tThe original and the restored aren't equal"); } }}

How can I save an Image object using serialization?Location: http://www.jguru.com/faq/view.jsp?EID=32308 Created: Apr 4, 2000 Modified: 2000-05-19 18:25:26.775Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

java.awt.Image does not implement Serializable, so if you need to send it to a stream using serialization you must access the underlying data representation and write that representation out explicitly.

Fortunately, there's an easy way to do this. Swing provides the javax.swing.ImageIcon class, which can be used as a serializable replacement for Image. ImageIcon has a constructor which accepts an Image, then stores a reference to that Image in a transient instance variable. ImageIcon defines writeObject() and readObject() methods which use the PixelGrabber class to convert the image to an array of integers for writing to the stream and the MemoryImageSource class to restore the image from the stream. An excerpt from the ImageIcon source is shown below.

ImageIcon provides a getImage() method for you to recover the stored Image object, so you may either use it directly or you may mimic the technique displayed in the source below to serialize images in your own code.

Page 23: Serialization FAQ From jGuru

/** * Excerpted from the javax.swing.ImageIcon source code */public class ImageIcon implements Icon, Serializable {

transient Image image;

/*

body of class has been removed... */

private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject();

int w = getIconWidth(); int h = getIconHeight(); int[] pixels = image != null? new int[w * h] : null;

if (image != null) { try { PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w); pg.grabPixels(); if ((pg.getStatus() & ImageObserver.ABORT) != 0) { throw new IOException("failed to load image contents"); } } catch (InterruptedException e) { throw new IOException("image load interrupted"); } } s.writeInt(w); s.writeInt(h); s.writeObject(pixels); }

private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject();

int w = s.readInt(); int h = s.readInt(); int[] pixels = (int[])(s.readObject());

if (pixels != null) { Toolkit tk = Toolkit.getDefaultToolkit(); ColorModel cm = ColorModel.getRGBdefault(); image = tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w)); } }}

Page 24: Serialization FAQ From jGuru

Note that using an integer for each pixel is an extremely inefficient way to save an image. GIF or JPEG encoded images can easily be 10 times more compact. If size is a concern, you might want to investigate other image formats. For example, at http://www.acme.com/ you can find classes that let you write an image out in GIF format. Alternatively, you can compress your array of integers before writing it to the stream.

Can I serialize an array directly, or do I have to wrap it in an object first?Location: http://www.jguru.com/faq/view.jsp?EID=34789 Created: Apr 11, 2000 Modified: 2000-04-11 10:46:05.17Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Although it's not obvious, arrays in Java are objects; they have methods you can invoke (toString(), equals(), etc.) and contain instance variables (length). The unnamed array superclass also implements Serializable, so all array types can be serialized directly, without any further work from the programmer, as shown in the following code example:

public class Test { public static void main(String[] args) throws Exception {

// Serialize an int[] ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.ser")); out.writeObject(new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); out.flush(); out.close();

// Deserialize the int[] ObjectInputStream in = new ObjectInputStream(new FileInputStream("test.ser")); int[] array = (int[]) in.readObject(); in.close();

// Print out contents of deserialized int[] System.out.println("It is " + (array instanceof Serializable) + " that int[] implements Serializable"); System.out.print("Deserialized array: " + array[0]); for (int i=1; i<array.length; i++) { System.out.print(", " + array[i]); } System.out.println(); }}

The usual restrictions apply, of course - if you have an array of objects, the contents of that array must also be serializable in order for the array to be successfully serialized.

My subclass implements Serializable but my superclass doesn't. Both subclass and superclass contain instance variables that need to be saved as part of the state of the subclass. Will serialization save the superclass fields for me?Location: http://www.jguru.com/faq/view.jsp?EID=34802

Page 25: Serialization FAQ From jGuru

Created: Apr 11, 2000 Modified: 2000-04-11 11:17:31.513Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

When you serialize an object, the serialization mechanism works by chaining up the inheritence hierarchy, saving the sate of each Serializable superclass in turn. When serialization reaches the first non-serializable superclass, the serialization stops.

When deserializing, the state of this first non-serializable superclass is restored not from the stream, but by invoking that class' no-argument constructor. If the no-argument constructor is not adequate for your purposes, you must customize the serialization of your subclass with writeObject() and readObject() in order to write out and restore any information from the non-serializable superclass that you find necessary.

Are there any other FAQs on Serialization?Location: http://www.jguru.com/faq/view.jsp?EID=35071 Created: Apr 11, 2000 Modified: 2000-04-11 21:08:53.926Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Sun's "Frequently Asked Questions on RMI and Object Serialization" is available at http://java.sun.com/products/jdk/1.2/docs/guide/rmi/faq.html. This is a list of FAQs taken from the RMI-USERS mailing list.

When using object streams over sockets, I have to flush the streams after each write operation. In fact I even have to flush the output stream soon after creation. Is there a way out of this?Location: http://www.jguru.com/faq/view.jsp?EID=35512 Created: Apr 12, 2000 Modified: 2000-04-12 12:47:14.803Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Viswanathan Kodaganallur (http://www.jguru.com/guru/viewbio.jsp?EID=35421

The ObjectOutput interface provides a flush() method, implying that implementations are allowed to buffer the output. The semantics of buffered output are such that if you want the data to be sent immediately, you need to flush the buffer (the FAQ at http://www.jguru.com/jguru/faq/view.jsp?EID=32701 talks about this as well).

It seems you are expecting to be able to read the data on the other end of the stream immediately after it is written; as you have found out, the only way to ensure that the data is sent over the socket immediately is to flush the buffer. The alternatives, setting the buffer size to be very small or turning off buffering entirely, are not available with socket output streams.

The other problem you mention, having to flush the buffer after creation of the ObjectOutputStream, is similar. Instantiating an ObjectOutputStream causes the stream header information to be written to the underlying (buffered) stream. On the other end, instantiating ObjectInputStream causes this header information to be read from the stream. If the output stream buffer hasn't been flushed, then the ObjectInputStream constructor will block until it can read the header information. Hence, when using buffered I/O, it is usually a good idea to flush the ObjectOutputStream right after creation. There is no other way to do this.

Page 26: Serialization FAQ From jGuru

What role does serialization have in RMI?Location: http://www.jguru.com/faq/view.jsp?EID=37229 Created: Apr 17, 2000 Modified: 2000-04-17 21:17:32.014Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by arshad mehmood (http://www.jguru.com/guru/viewbio.jsp?EID=37224

RMI uses serialization as its basic and only mechanism for sending objects across a network.

If an object implements java.rmi.Remote, then the object's stub is serialized and sent to the client. If the object implements java.io.Serializable, then the object itself is serialized and sent.

Can I pass Externalizable objects by value using RMI, or do the objects have to implement Serializable directly?Location: http://www.jguru.com/faq/view.jsp?EID=38866 Created: Apr 21, 2000 Modified: 2000-04-21 13:33:51.951Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

RMI will allow you to pass any object that is serializable according to the serialization specification. This includes objects that implement Externalizable as well as objects that implement Serializable.

Note that Externalizable extends Serializable, so anywhere you see the use of the generic term "serializable" you can assume it refers to objects that implement either of these interfaces.

How do I use the @serialField javadoc tag?Location: http://www.jguru.com/faq/view.jsp?EID=38867 Created: Apr 21, 2000 Modified: 2000-04-21 16:45:02.083Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

If you declare your serialiazable fields using the serialPersistentFields member (see FAQ http://www.jguru.com/jguru/faq/view.jsp?EID=1197) then you should document these fields using the @serialField javadoc tag. The syntax of this tag is:

@serialField field-name field-type field-descriptionThe serialPeristentFields member is an array of ObjectStreamField objects, declared as follow: private static final ObjectStreamField[] serialPeristentFields;You should have one @serialField tag for each element of the serialPersistentFields array. These tags should appear in the javadoc comment preceding the declaration of serialPersistentFields.

In the standard javadoc output, this information is displayed only in the "Serialized Form" page for that class.

The javadoc documentation for every Swing class contains the warning that "Serialized objects of this class will not be compatible with future Swing

Page 27: Serialization FAQ From jGuru

releases." What exactly does this mean, and how does it affect how I write my Swing applications?Location: http://www.jguru.com/faq/view.jsp?EID=38977 Created: Apr 21, 2000 Modified: 2000-04-25 06:11:06.652Author: Praful Kapadia (http://www.jguru.com/guru/viewbio.jsp?EID=38976) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

From the JBuilder documentation:

Serializing JavaBeans

Serializing an object is the process of turning its state into a sequence of bytes that is neither a .java nor a .class file. Why would you want to do such a thing? That sequence of bytes can be saved as a file on a disk or sent over a network. When a request is made to restore an object from a file or on the other end of a network connection, the sequence of bytes is deserialized into its original structure.

For JavaBeans, serialization provides a simple way to save the state of a bean between one session and another. This is also called component persistence. For example, suppose the user of a bean changes the values of several properties. If the bean is serialized to a file and then deserializing the next time the user uses it, the bean is restored exactly as the user left it.

Sun hadn't yet decided the final format for serialized objects. I suspect when they do, they'll opt for XML format.

For now you may want to avoid serializing your objects.

[FAQ Manager Note] Sun has released the specs of the new XML serialization. See http://java.sun.com/products/jfc/tsc/articles/persistence/index.html for details

How can I make a deep copy of an object using serialization?Location: http://www.jguru.com/faq/view.jsp?EID=39089 Created: Apr 22, 2000 Modified: 2000-04-22 11:22:15.904Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

See http://www.jguru.com/jguru/faq/view.jsp?EID=20435.

Why would I want to implement Externalizable instead of Serializable?Location: http://www.jguru.com/faq/view.jsp?EID=42504 Created: Apr 30, 2000 Modified: 2000-05-01 09:45:05.552Author: Andre van Dalen (http://www.jguru.com/guru/viewbio.jsp?EID=7570) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

By implementing Externalizable yourself you can win performance at the cost of flexibility and extra code to maintain. If you implement Externalizable yourself you stream the data directly without the need for reflection which is used in the case of Serializable.

Page 28: Serialization FAQ From jGuru

See http://developer.java.sun.com/developer/TechTips/2000/tt0425.html for an example.

Comments and alternative answers

Externalization is also useful for working around ... Author: Paul Brinkley (http://www.jguru.com/guru/viewbio.jsp?EID=298984), Feb 7, 2001Externalization is also useful for working around serialization bugs in classes you don't control. For instance, a third-party (or JFC!) class may be specified as Serializable, but it throws an exception when serialized or deserialized.

You can subclass this class into one that's Externalizable and define a no-argument constructor for it. The implement your constructor to call whichever superclass constructor pleases you. Implement writeExternal() by saving off the fields you're interested in. Implement readExternal() to read these fields back in and reconfigure the superclass. In this way, you effectively take over all serialization work; it's as if the superclass doesn't even implement Serializable.

ObjectOutputStream seems to be holding a reference to all the objects in my large graph, even after I close the stream. This keeps my objects from being garbage collected. Is this a bug?Location: http://www.jguru.com/faq/view.jsp?EID=42980 Created: May 1, 2000 Modified: 2000-05-01 11:38:10.933Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

ObjectOutputStream holds a reference to all the objects in the graph so it can handle circular references by noticing when an object has already been serialized. The only way to clear these references is by invoking reset() on the stream. The close() method does not do this, so unless you reset the stream explicitly, those references will be held until the ObjectOutputStream instance is itself garbage collected. This may take some time. Comments and alternative answers

Is this also true with ObjectInputStream? Author: Joen Moreno (http://www.jguru.com/guru/viewbio.jsp?EID=134600), Nov 8, 2000Is this also true with ObjectInputStream?

I keep getting a StackOverflowError when I try to serialize my objects. What does this mean and how can I stop it?Location: http://www.jguru.com/faq/view.jsp?EID=42981 Created: May 1, 2000 Modified: 2000-05-01 11:38:58.566Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Serialization is a recursive process. If your object graph is too deep, then you could overflow the JVM stack. To prevent this, implement readObject() and

Page 29: Serialization FAQ From jGuru

writeObject() and use your superior knowledge of the structure of your object graph to efficiently serialize your objects.

How can I programmatically obtain the serialVersionUID for a class?Location: http://www.jguru.com/faq/view.jsp?EID=42982 Created: May 1, 2000 Modified: 2000-11-26 08:58:05.403Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

The following piece of code shows you how to do this for the class java.lang.String: String s = new String("test"); Class cl = s.getClass(); long uid = ObjectStreamClass.lookup(cl).getSerialVersionUID();The value of uid will be the same as the value printed out by serialver java.lang.String.

What are the writeReplace() and readResolve() methods used for?Location: http://www.jguru.com/faq/view.jsp?EID=44039 Created: May 3, 2000 Modified: 2000-05-03 11:08:47.974Author: Chuck McCorvey (http://www.jguru.com/guru/viewbio.jsp?EID=42393) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

These methods are used to allow an object to provide an alternative representation for itself within an ObjectStream. Consider for instance the common means of implementing an enumerated type:

public class Gender implements Serializable { public final static Gender MALE = new Gender("Male"); public final static Gender FEMALE = new Gender("Female");

private String name;

private Gender(String name) { this.name = name; }}This works fine within one JVM; there will be at most two Gender objects created, no matter how often you use Gender.MALE and Gender.FEMALE in your code. However, consider what happens when an instance of this class is serialized across JVMs. The ObjectInputStream will create a new instance of Gender that has the same value as the original instance. So, if you have many thousands objects that have been de-serialized via RMI you might end up with many thousands of extra instances of Gender. The writeReplace() and readResolve() methods are the hook to solve this problem.

One way of eliminating the extra instances and some of the unnecessary heap allocation would be to do something like this:

public class Gender implements Serializable { public final static Gender MALE = new Gender("Male"); public final static Gender FEMALE = new Gender("Female");

private String name;

Page 30: Serialization FAQ From jGuru

private Gender(String name) { this.name = name; }

Object writeReplace() throws ObjectStreamException { if (this.equals(MALE)) { return SerializedForm.MALE_FORM; } else { return SerializedForm.FEMALE_FORM; } }

private static class SerializedForm implements Serializable {

final static SerializedForm MALE_FORM = new SerializedForm(0); final static SerializedForm FEMALE_FORM = new SerializedForm(1);

private int value;

SerializedForm(int value) { this.value = value; }

Object readResolve() throws ObjectStreamException { if (value == MALE_FORM.value) { return Gender.MALE; } else { return Gender.FEMALE; } } }}This also guarantees that in all cases where genderInstance.equals(MALE) is true, genderInstance == Gender.MALE is also true.

This was a trivial example. I've used this mechanism in other instances where a great deal of storage or time could be saved by serializing only a shorthand or mnemonic form of the object - consider the definition of a currency which could be serialized as only its mnemonic symbol.

How has Serialization changed in the Java 2 SE SDK, v1.3?Location: http://www.jguru.com/faq/view.jsp?EID=44246 Created: May 3, 2000 Modified: 2000-05-03 17:32:13.317Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Serialization has improved in three key ways: 1. Speed of reading and writing serialized objects was improved up to 40%. This

also dramatically improves RMI performance. 2. Limit of 64K on the size of strings has been removed. This entailed changes in

the serialization protocol. Older versions of the Java SDK still can't read these long Strings, and will generate a java.io.StreamCorruptedExceptio if they encounter this new protocol.

3. More specific information is reported when an exception occurs during deserialization. This is important for RMI because code movement and

Page 31: Serialization FAQ From jGuru

dynamic class loading are particularly hard to debug unless specific error messages are generated.

Is writing an object to an ObjectOutputStream a thread-safe operation?Location: http://www.jguru.com/faq/view.jsp?EID=44251 Created: May 3, 2000 Modified: 2000-05-03 17:36:32.876Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Absolutely not! Serialization, i.e. passing an object reference to the writeObject() method of ObjectOutputStream, is not an atomic operation. Serialization involves traversing a graph of objects, each of which contributes to the state of the object being serialized, saving the state of each object in turn. This is a time-consuming procedure; if other threads are allowed to concurrently access or modify any one of the objects in the graph you could get underfined and unwanted results.

The solution is to protect the objects in the graph from modification during the serialization, or to design your objects such that the graph is consistent even if individual objects are modified during serialization. This is, in general, a non-trivial task. Proper use of the transient keyword and customization of serialization through the use of readObject() and writeObject() will allow you to control exactly what parts of your graph are serialized.

Does serialization support encryption?Location: http://www.jguru.com/faq/view.jsp?EID=44567 Created: May 4, 2000 Modified: 2000-05-04 08:37:06.035Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Not directly. I/O in Java is performed through streams, and encryption is typically implemented as an algorithm operating on a stream - the input to the stream is clear text, the output is encrypted.

Serialization is stream-oriented, so any encryption that can be performed on any stream can also be applied to serialized objects.

Comments and alternative answers

GZip can give limited encryption Author: Simon Billingsley (http://www.jguru.com/guru/viewbio.jsp?EID=458934), Jul 20, 2001When performing serialization you can provide limited encryption of the data within the serialized file by passing the file data through a GZIP filter before writing it to disk. You then need to rememember to pass it through a GZIP filter on the way back in.

Although this isn't true encryption, because they can always 'decrypt' the data using gunzip on the command line, it prevents the data from being viewed in a file editor directly.

See the classes java.util.zip.GZipOutputStream and java.util.zip.GZipInputStream for more information.

Page 32: Serialization FAQ From jGuru

Can an object of type Class be serialized?Location: http://www.jguru.com/faq/view.jsp?EID=48741 Created: May 13, 2000 Modified: 2000-05-15 20:23:48.879Author: raghu rao (http://www.jguru.com/guru/viewbio.jsp?EID=48735) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

Yes, it can. Class implements Serializable, so a object of type Class can be serialized.Comments and alternative answers

All versions of Java through 1.3 have a bug doing this... Author: Marius Strumyla (http://www.jguru.com/guru/viewbio.jsp?EID=29146), May 30, 2000

All versions of Java through 1.3 have a bug doing this for some cases. On an attempt to deserialize classes of primitive types (e.g., int.class, boolean.class), the JVM throws a java.lang.ClassNotFoundException.

For possible workaround to this bug see http://developer.java.sun.com/developer/bugParade/bugs/4171142.html.

What are the security considerations for serialization?Location: http://www.jguru.com/faq/view.jsp?EID=57249 Created: May 25, 2000 Modified: 2000-05-25 23:59:27.342Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

The Java runtime environment has many features that contribute to security and robustness in a program. For example, the runtime environment enforces access permissions to private, protected, or "default" members. But when you serialize your objects, you are in effect removing them from the runtime environment, thereby exposing them to access that would normally not be allowed - e.g. anyone can come along and read the contents of a private variables from a serialized object. This is why it is important to consider security when you are designing your classes for serialization.

Java provides a number of mechanisms to protect your serialized code:

The first is the obvious step that classes need to be explicitly declared as implementing Serializable or Externalizable - your class cannot be serialized without a concious decision on your part to make it so.

Java provides a transient keyword which prevents a primitive type or object reference from being written to the stream. You may use this to control which information is sent out. For example, you may mark a private password field as transient so that it isn't written out - this prevents someone from coming along and reading your password directly from a serialized object.

Serialization is a stream-oriented process, so you may apply any stream-based encryption to your serialized objects.

Page 33: Serialization FAQ From jGuru

Deserialization can't overwrite existing objects in memory - it can only create new objects.

Loading classes for serialized objects is done through the normal class loader mechanism, therefore is protected by the usual Java security mechanisms.

One other things to consider: If you are implementing Externalizable, both readExternal() and writeExternal() are public, so it is possible to replace objects in memory when reading and it is possible to override writeExternal() to gain access to private data when writing. If you want to enforce safety, you should either not use Externalizable or take additional steps to avoid these problems.

The above is not a comprehensive list; more information on this subject may be found at: http://java.sun.com/security/seccodeguide.html and http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/security.doc.html.

How can I read and write serialized objects to and from a database?Location: http://www.jguru.com/faq/view.jsp?EID=74403 Created: Jun 13, 2000 Modified: 2000-06-13 12:12:18.258Author: Simon Brown (http://www.jguru.com/guru/viewbio.jsp?EID=44588) Question originally posed by edwin abiraham (http://www.jguru.com/guru/viewbio.jsp?EID=41880

If your RDBMS supports them, you can store serialized objects as BLOBs.

These are JDBC 2.0 features, but take a look at java.sql.Blob, ResultSet and PreparedStatement for more information.

Comments and alternative answers

Storing Objects as Text Author: Scott McKinney (http://www.jguru.com/guru/viewbio.jsp?EID=727047), Jan 19, 2002You could store relatively small objects in VARCHAR fields by encoding the byte array e.g., using the Base64 encoding.

Alternatively, instead of using standard java serialization you might consider storing an object in XML using your own (or third-party) serialization scheme. Since the objects are stored in XML you have the benefit using VARCHAR fields as well.

Base64 Encoding Author: Stephen Ostermiller (http://www.jguru.com/guru/viewbio.jsp?EID=576685), Sep 24, 2002Open source, GPL implementation from com.Ostermiller.util:http://ostermiller.org/utils/Base64.htmlIt can encode and decode strings, byte arrays, files, and streams.

Open source, public domain encoder/decoder by Robert W. Harder:http://iharder.sourceforge.net/base64/

Page 34: Serialization FAQ From jGuru

Encodes to strings from several formats including byte arrays and strings. It has a method of encoding and decoding streams but it looks awkward.

Open source, freeware (except military) from Roedy Green's Java Glossary:http://mindprod.com/jglossbase64.htmlhttp://mindprod.com/products.html#BASE64Encodes from byte arrays to strings, decodes from strings to byte arrays.

Open source, GPL implementation by Kevin Kelley:http://kevinkelley.mystarband.net/java/goodies.htmlEncodes and decodes from byte arrays to byte arrays.

Open source, freeware (any purpose with attribution) by Bob Withers:http://www.ruffboy.com/download.htmEncodes and decodes from byte arrays to byte arrays and comes with C++ code too.

JavaWorld tip with annotated code and nifty graphic that shows how Base64 encoding works (license unknown). http://www.javaworld.com/javaworld/javatips/jw-javatip36-p2.htmlSupports byte array to byte array operations.

I am able to write an object using ObjectOutputStream but when I try to read the object back using ObjectInputStream I get a StreamCorruptedException. How can I overcome this? Location: http://www.jguru.com/faq/view.jsp?EID=76047 Created: Jun 14, 2000 Modified: 2001-05-22 08:27:30.431Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Kartick Neogi (http://www.jguru.com/guru/viewbio.jsp?EID=50612

The serialization specification says that a StreamCorruptedException is thrown: If the stream header is invalid. If control information not found. If control information is invalid. JDK 1.1.5 or less attempts to call readExternal() on a PROTOCOL_VERSION_2

stream.

The last item is probably the most common problem - it will occur if you write out an Externalizable object using Java version 1.2 and try to read it in using Java version 1.1.5 or less. The other reasons might occur if, for example, you transferred the .ser file to a different computer by FTP and forgot to use binary mode.

One additional cause of StreamCorruptedException that is not explicitly mentioned in the specification is if you try to deserialize a String of length >64kB into a pre-version 1.3 JVM. Prior to Java version 1.3, serialization of String objects of this length was not supported.

Page 35: Serialization FAQ From jGuru

Comments and alternative answers

How can get rid of serialize ID or make it unchange in respect to different version of jdk? Author: Stephen Koo (http://www.jguru.com/guru/viewbio.jsp?EID=477108), Aug 14, 2001I use VisualAge for Java (jdk 1.2.2) to program the DefaultStyledDocument, I have generated and save some data in the IDE too. Afterthat, I deployed the application and use standard Java runtime engine 1.3x to execute it, but the program cannot read back the saved data in the IDE, the error is as follows:

java.io.InvalidClassException: javax.swing.text.DefaultStyledDocument; Local class not compatible: stream classdesc serialVersionUID=-3720453677177430838 local class serialVersionUID=3189459741008450845 at java.io.ObjectStreamClass.validateLocalClass(Unknown Source) at java.io.ObjectStreamClass.setClass(Unknown Source) at java.io.ObjectInputStream.inputClassDescriptor(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at java.io.ObjectInputStream.inputObject(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at Formatter.doOpenCommand(Formatter.java:172) at Formatter$2.actionPerformed(Formatter.java:49) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknow n Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.AbstractButton.doClick(Unknown Source) at javax.swing.plaf.basic.BasicMenuItemUI$MouseInputHandler.mouseRelease d(Unknown Source)

Can I serialize an object that has native methods?Location: http://www.jguru.com/faq/view.jsp?EID=77054 Created: Jun 15, 2000 Modified: 2000-06-15 12:23:17.667Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

Method implementations, whether native or pure Java, are not part of the serialized state of an object. There is nothing that prevents objects with native methods from being serialized.

It might however be problematic in practice to reconstitute these objects if the native code can't be loaded, e.g. when sending serialized objects over a socket where the other end doesn't have the native library installed. It is of course also a problem if the other end can't load the .class files, but native libraries can't be dynamically downloaded like .class files.

Page 36: Serialization FAQ From jGuru

Is there a way to serialize an object as an XML document? Location: http://www.jguru.com/faq/view.jsp?EID=79287 Created: Jun 18, 2000 Modified: 2000-06-18 00:58:13.512Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7) Question originally posed by Daniel Jutzi (http://www.jguru.com/guru/viewbio.jsp?EID=43200

The Java serialization mechanism uses an efficient, compact format for encoding information about class structure and the values for instance variables. The eXtensible Markup Language (XML) provides a text-based approach for encoding structured data, and could also be used to encode the serialization information, albeit in a much less compact but more readable format. It should come as no surprise that this approach is being investigated to determine if it is appropriate under certain circumstances. The reference at the end of this answer provides a link to an article by Philip Milne and Kathy Walrath at The Swing Connection which illustrates such a technique by defining a persistence model which writes object graphs as XML documents. In this article, they define, among other things, an XML format for JavaBeans, and streams XMLOutputStream and XMLInputStream. The following is an example taken from that article which illustrates the XML format for a simple serialized JPanel object.

<JAVA-OBJECT-ARCHIVE VERSION="0.1"> <CLASS ID="JPanel" NAME="javax.swing.JPanel"/> <CLASS ID="JButton" NAME="javax.swing.JButton"/> <CLASS ID="Test" NAME="Test"/> <CLASS ID="Rectangle" NAME="java.awt.Rectangle"/> <CLASS ID="Integer" NAME="java.lang.Integer"/> <CLASS ID="JTextField" NAME="javax.swing.JTextField"/> <OBJECT ID="JPanel0" CLASS="JPanel"> <OBJECT METHOD="add"> <OBJECT ID="JButton0" CLASS="JButton"> <OBJECT METHOD="addActionListener"> <OBJECT CLASS="Test"/> </OBJECT> <OBJECT PROPERTY="bounds" CLASS="Rectangle"> <OBJECT CLASS="Integer" VALUE="10"/> <OBJECT CLASS="Integer" VALUE="20"/> <OBJECT CLASS="Integer" VALUE="100"/> <OBJECT CLASS="Integer" VALUE="20"/> </OBJECT> <OBJECT PROPERTY="text" VALUE="cut"/> </OBJECT> </OBJECT> <OBJECT METHOD="add"> <OBJECT ID="JTextField0" CLASS="JTextField"> <OBJECT PROPERTY="nextFocusableComponent" IDREF="JButton0"/> <OBJECT PROPERTY="bounds" CLASS="Rectangle"> <OBJECT CLASS="Integer" VALUE="30"/> <OBJECT CLASS="Integer" VALUE="50"/> <OBJECT CLASS="Integer" VALUE="200"/> <OBJECT CLASS="Integer" VALUE="20"/> </OBJECT> </OBJECT> </OBJECT> <OBJECT PROPERTY="layout"/> <OBJECT PROPERTY="bounds" CLASS="Rectangle">

Page 37: Serialization FAQ From jGuru

<OBJECT CLASS="Integer" VALUE="0"/> <OBJECT CLASS="Integer" VALUE="0"/> <OBJECT CLASS="Integer" VALUE="539"/> <OBJECT CLASS="Integer" VALUE="366"/> </OBJECT> </OBJECT> </JAVA-OBJECT-ARCHIVE>

The use of XML in this manner is not officially part of the Java language, and a detailed discussion of this topic is beyond the scope of this FAQ. The article by Philip Milne and Kathy Walrath provides additional information for the interested reader [http://java.sun.com/products/jfc/tsc/articles/persistence/].

Can a Vector or a Hashtable be serialized and deserialized? Location: http://www.jguru.com/faq/view.jsp?EID=86167 Created: Jun 24, 2000 Modified: 2000-11-10 10:17:29.927Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Cailassame Nedunchezhian (http://www.jguru.com/guru/viewbio.jsp?EID=85961

Both these classes implement Serializable, and have been designed for serialization. So yes, they can be serialized.

One thing you have to watch out for, though, is that in order to serialize a collection like Vector or Hashtable, you must also be able to serialize all of the objects contained in these collections. Otherwise, the collection would not be able to be completely restored. Your program will throw a NotSerializableException unless all objects stored in the Vector or Hashtable are also serializable.

How can I change the names of instance variables in a class which is Serializable and still be able to read serialized files from a previous version of the class? If I use serialver to create a version ID then implement readObject(), how would I know in which order to read in the instance variables from the old serialized files?Location: http://www.jguru.com/faq/view.jsp?EID=88641 Created: Jun 27, 2000 Modified: 2000-06-27 14:33:47.922Author: Hugh Robinson (http://www.jguru.com/guru/viewbio.jsp?EID=42047) Question originally posed by Hugh Robinson (http://www.jguru.com/guru/viewbio.jsp?EID=42047

One way to solve this is to override the readObject() instance method in the class which you are serializing and whose variable names have changed.

In this method, you can use the ObjectInputStream.readFields() method to return an ObjectInputStream.GetField object, which can then be interrogated one variable at a time.

Suppose that in version 1, the class had instance variables named m_str1 and m_n1 and in version 2, it had m_str2 and m_n2. Then:

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {

Page 38: Serialization FAQ From jGuru

ObjectInputStream.GetField gf = in.readFields();

if ((String) gf.get("m_str2", null) != null) { // Version 2 file detected // defaultReadObject() would suffice here, but it's // too late to call it! m_str2 = (String) gf.get("m_str2", null); m_n2 = (int) gf.get("m_n2", null); } else { // Version 1 file detected m_str2 = (String) gf.get("m_str1", null); m_n2 = (int) gf.get("m_n1", null); }}The downside of this is that it seems to take about 150% of the CPU time (I tested it in JDK 1.3, which is faster at serialization than JDK 1.2.2) compared to using the default read mechanism. This may be important if you are reading a lot of objects of this class.

The problem here is that if you call readFields() to determine the version of the class, you have then read all of the persistent fields for the class and you then (presumably) have to get the fields using gf.get(). It would instead be nice to be able to detect the old version without incurring the speed hit when reading the new version.

The only way that I can think of is to write a version number at the beginning of the stream using some Version class. Then the hit would only be felt on one (small) class.

What is an object graph?Location: http://www.jguru.com/faq/view.jsp?EID=90029 Created: Jun 28, 2000 Modified: 2000-06-28 11:15:11.706Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

When used in connection with serialization, an object graph is a tree structure rooted at the object you have written to the ObjectOutputStream. The branches and leaves of the tree are all the objects which are reachable by following references from the root object. This structure is maintained by the ObjectOutputStream in order to ensure that the complete reachable state of the given object is serialized and to handle cyclic dependencies. The graph is computed on-the-fly, during the serialization process.

A side-effect of maintaining this graph is that an object which has already been written to the stream will not be written again - it will be replaced by an object stream identifier, simply a number used to point at the previously object. To force a changed object to be written in its entirety, you need to reset() the stream, which clears the object graph. See http://www.jguru.com/jguru/faq/view.jsp?EID=25970 for more information.

Comments and alternative answers

Page 39: Serialization FAQ From jGuru

"[A]n object graph is a tree structure"... Author: Brendan Macmillan (http://www.jguru.com/guru/viewbio.jsp?EID=227597), Nov 25, 2000

"[A]n object graph is a tree structure" is technically incorrect. A tree structure is like a real tree, in that the branches never meet up again. However, two Java references "pointing" at the same object is precisely equivalent to branches of a tree joining up again.

You can also have branches that loop back to an earlier part of the tree - or "circular references". These rather odd "trees" are properly called "graphs".

What is ObjectStreamClass used for?Location: http://www.jguru.com/faq/view.jsp?EID=93254 Created: Jul 2, 2000 Modified: 2000-07-02 09:10:35.056Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

The ObjectStreamClass is used to check if the version of a serialized class (.ser file) is compatibile with the version of a class in memory/loadable from the CLASSPATH. See How can I programmatically obtain the serialVersionUID for a class? for an example of its usage.

It can also be used to get a descriptor for the fields in the stream. See the Serialization Specification for more information.

What is ObjectStreamField used for?Location: http://www.jguru.com/faq/view.jsp?EID=93257 Created: Jul 2, 2000 Modified: 2000-07-02 09:11:59.397Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7) Question originally posed by Tim Rohaly PREMIUM (http://www.jguru.com/guru/viewbio.jsp?EID=10

Starting with Java 2 Standard Edition, version 1.2, instead of using the transient keyword to define what fields are serializable within a class, you may create an array of ObjectStreamField objects to define the serializable fields within the class. This is demonstrated in How should I declare fields within my serializable class to prevent them from being serialized?

What is a serialized bean?Location: http://www.jguru.com/faq/view.jsp?EID=100726 Created: Jul 12, 2000 Modified: 2000-07-12 15:36:48.624Author: Andreas Schaefer (http://www.jguru.com/guru/viewbio.jsp?EID=25162) Question originally posed by manoj agrawal (http://www.jguru.com/guru/viewbio.jsp?EID=70415

Page 40: Serialization FAQ From jGuru

You can deliver a bean as either its bytecode (compiled Java code) or as a serialized object (after the bean instance is serialized to a file (*.ser)).

The difference is that when you load the bean by its bytecode the bean loader normally create an instance from it by calling the default constructor (no arguments constructor). If you have a serialized instance the loader creates the instance like it was when it was serialized and therefore its internal state is recreated (except transient fields).

Therefore you can provide already customized beans for a particular purpose instead of letting the bean user do this. So you can provide beans for the different Swing look and feels which vary in its background color, borders, fonts, etc. Then the bean user can select for the one he prefers instead of trying settings the bean properties.

See also:

Why do we need a no argument constructor in a JavaBean component? What are pros/cons of instantiating a swing object using "new" vs. using

"Beans.instantiate"? How do I restore a JavaBean from a saved version?

How can I serialize an object into a byte array?Location: http://www.jguru.com/faq/view.jsp?EID=103437 Created: Jul 16, 2000 Modified: 2000-07-16 23:57:26.022Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Aleksandar Matijaca (http://www.jguru.com/guru/viewbio.jsp?EID=102223

Wrap an ObjectOutputStream around a ByteArrayOutputStream. Serializing an object to the ObjectOutputStream will then store the object in the byte array: ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(myObject);To restore this object, reverse the process: ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);Object myObject = ois.readObject();

How can I modify a serialized object which is stored in a file if the file contains a large number of objects?Location: http://www.jguru.com/faq/view.jsp?EID=114601 Created: Jul 30, 2000 Modified: 2000-07-31 12:16:49.23Author: Doug Bell (http://www.jguru.com/guru/viewbio.jsp?EID=113602) Question originally posed by balaji chittu (http://www.jguru.com/guru/viewbio.jsp?EID=95194

The short answer is that you probably can't without deserializing the objects and reserializing and rewriting the objects.

The serialized format is truly a stream-oriented protocol and does not support random access--it is both self-referential and incremental. When an object is written to the stream, a description of the class and its non-static and non-transient fields (including any Serializable superclasses and their non-static and non-transient

Page 41: Serialization FAQ From jGuru

fields) is also written to the steam. Then the entire object graph of non-transient fields of Serializable classes is written, which means that non-null object references to serializable objects are recursively serialized. Throughout this process, object identity is maintained by adding object handles to a table maintained by both ObjectOutputStream and ObjectInputStream. When an object previously encountered in the stream is serialized, only the object handle is written to the stream. Object handles are used to maintain identity for not only objects, but also the class descriptions and even the strings used for class and field names.

So even if you had the offset within the stream of the object you want to modify, without having processed all of the preceeding content it is unlikely that all the data needed to interpret the serialized data for the object would be present.

Note that the reset() method of ObjectOutputStream can be used during serialization to reset the table of object handles. This may allow you to devise a means of serializing your objects in a more localized manner. However, resetting the stream means that any previously written objects will be serialized as separate objects, and consequently, deserialized as separate objects. In other words, object references that previosuly referred to the same object will refer to different objects after deserialization.

How can an applet read a serialized object residing in the same directory? Location: http://www.jguru.com/faq/view.jsp?EID=118958 Created: Aug 4, 2000 Modified: 2000-08-04 09:31:07.376Author: Jon Wingfield (http://www.jguru.com/guru/viewbio.jsp?EID=41079) Question originally posed by amol sinha (http://www.jguru.com/guru/viewbio.jsp?EID=84027

Normally when de-serializing from a file one would use a FileInputStream. However, in the case of an untrusted applet you can use an InputStream derived from the applet's document base URL. To load a file "myClass.ser" residing in the same directory use:

try { InputStream is = new URL(getDocumentBase(), "myClass.ser").openStream(); ObjectInputStream ois = new ObjectInputStream(is); Object o = ois.readObject(); System.out.println(o); ois.close();} catch (ClassNotFoundException cnfe) { System.out.println(cnfe);} catch (IOException ioe) { System.out.println(ioe);}A more general mechanism would be to use the static getResourceAsStream(...) method of ClassLoader. This searches for the resource along the application classpath and returns an InputStream to the resource. The serialized object file can now be either on the Web Server or bundled as part of the applet's jar archive. If the serialized file is not being changed by some other process then it would make sense to have it in the jar as this reduces the number of requests the applet needs to make to the server.

If de-serialization of objects is being used to reduce initialization time of your applet you could use the OBJECT attribute of the APPLET tag to specify a serialized version

Page 42: Serialization FAQ From jGuru

of the entire applet. However, care is needed if you use this feature. For additional info see http://java.sun.com/products/jdk/1.1/docs/guide/misc/applet.html.

Why should I implement readObject() even if I don't implement writeObject()?Location: http://www.jguru.com/faq/view.jsp?EID=120641 Created: Aug 6, 2000 Modified: 2000-08-06 20:56:40.05Author: John Mitchell (http://www.jguru.com/guru/viewbio.jsp?EID=4)

It's a good idea to think of deserialization as yet another public constructor. So, if you have any post-construction activities that you want your object to deal with such as initialization of transient fields, validation, registering for events, etc. then you should implement readObject(). Remember to have it call defaultReadObject() first and then do your thing. Comments and alternative answers

why defaultReadObject() necessary? Author: Kyaw Tun (http://www.jguru.com/guru/viewbio.jsp?EID=1196288), Aug 30, 2004I write all necessary data in my readObject(). So I can skip defaultReadObject() to gain some speed.

Where can I find the official documentation of the Sun Java SDK tools?Location: http://www.jguru.com/faq/view.jsp?EID=138528 Created: Aug 30, 2000 Modified: 2000-08-30 11:20:52.803Author: John Mitchell (http://www.jguru.com/guru/viewbio.jsp?EID=4)

You can find the official Sun documentation for all of the tools in the Java 2 SDK including javac, java, javadoc, appletviewer, jar, jdb, javah, javap, extcheck, rmic, rmiregistry, rmid, serialver, native2ascii, keytool, jarsigner, policytool, tnameserv, idlj, and unregbean on the Java 2 SDK Tools and Utilities page.

Are methods also serialized along with the data members?Location: http://www.jguru.com/faq/view.jsp?EID=209416 Created: Sep 18, 2000 Modified: 2000-09-18 15:33:43.646Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Sunder Raman Venkataraman (http://www.jguru.com/guru/viewbio.jsp?EID=64503

No. Method bodies do not hold any information on the state of an object, so they are not needed in order to save or restore the state.Comments and alternative answers

Serialization is for saving the state of an object... Author: V S N Murthy Boggavarapu (http://www.jguru.com/guru/viewbio.jsp?EID=63013), Oct 18, 2000Serialization is for saving the state of an object instance, whereas the object's methods and static fields are class-level properties. So, there is no need to serialize methods and static members.

Page 43: Serialization FAQ From jGuru

Re: Serialization is for saving the state of an object... Author: krishna raj (http://www.jguru.com/guru/viewbio.jsp?EID=1180669), Jun 22, 2004But when a method is invoked on an object that has been serialized and sent across from another JVM, does this method invocation have to happen on the original object and not on the serialized object, thus involving a network call. For Eg. let's assume a client/server scenario (either Sockets or RMI) with CustomerManager and Customer classes in the server. Only Customer class implements Serializable. 1. Client creates CustomerManager (gets a reference only since it is not serializable) and calls a create() method (assume) on CustomerManager to create a Customer. 2. The above call goes to the server and returns a Serialized Customer object to the client (via proxy/stub or whatever). 3. Client invokes getCustName() method on Customer. Suppose this method returns the Customer Name in upper case. Does this method invocation have to go back to the Server ?Does the client have the implementation of the method as part of the serialized object, so that the method can be executed locally ?

Is there any significant performance gain in serialization from declaring instance variables as transient? Location: http://www.jguru.com/faq/view.jsp?EID=209431 Created: Sep 18, 2000 Modified: 2000-09-18 13:55:12.631Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Sunder Raman Venkataraman (http://www.jguru.com/guru/viewbio.jsp?EID=64503

Serialization saves only the state of the object. If some instance variables don't contribute to the state, there's no sense in spending the extra time and bytes serializing them. As for how much performance you'll gain, that depends on your objects. If the instance variables are primitives, you won't save much, but if the instance variables are object references, the savings can be much greater.

If however the instance variable you declare transient are part of the state of the object, you will need to reconstruct the transient values upon deserializing. This requires you to implement private void readObject() and private void writeObject(). In general, objects which implement readObject() and writeObject() have better serialization performance because the object streams don't have to use reflection as much to figure out the detailed structure of the object. But this is by no means a hard-and-fast rule - it's easy to decrease performance by an inefficient readObject() or writeObject() method.

The only sure way to find out is to test it with your own objects, within your own application. Trying to "tune" the performance of your application by setting variables to be transient is probably not a good thing to do - it would be much better to design your objects for serialization from the start by understanding, on an object-by-object basis, what information needs to be serialized and making sure that variables which don't constitute the state are declared transient.

Further information about improving performance of serialization can be found at:

Page 44: Serialization FAQ From jGuru

http://www.jguru.com/jguru/faq/view.jsp?EID=3419andhttp://www.jguru.com/jguru/faq/view.jsp?EID=42504

Is there any way to save the state of an object of a class which does not implement Serializable or Extenalizable?.Location: http://www.jguru.com/faq/view.jsp?EID=221619 Created: Oct 3, 2000 Modified: 2000-10-20 11:48:44.577Author: swarraj kulkarni (http://www.jguru.com/guru/viewbio.jsp?EID=121306) Question originally posed by poobalan r (http://www.jguru.com/guru/viewbio.jsp?EID=219451

Yes. You will have to write the value of each and every instance variable into the persistent storage. If there are 100 variables, you will have to store each of them individually. If some of the variables are object references, you will have to follow each reference and save the state of that object as well. You can do that, but it would be a proprietary solution and each class that wanted to read your object would also have to know all about your proprietary format. Comments and alternative answers

You can always make a non-serializable class into a... Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10), Oct 20, 2000You can always make a non-serializable class into a serializable one by subclassing. You might still have to manually write the code for saving the state of the parent class, but you could do it inside the framework of serialization by adding readObject() and writeObject() methods. If you do this then your object can be read and written using standard serialization, yet you still have full control over the external format of the data.

Use JSX instead Author: Brendan Macmillan (http://www.jguru.com/guru/viewbio.jsp?EID=569814), Dec 2, 2001Use JSX. JSX (Java Serialization to XML) subclasses the Serialization classes, so it can be used as a direct replacement for them. It serializes all objects, and does not require them to implement Serializable or Externalizable interfaces.

As a direct replacement, it also handles all the other aspects of serialization, such as invoking an objects readObject() and writeObject() methods.

As a bonus, the output is in XML, so you can read what the state is manually.

http://www.csse.monash.edu.au/~bren/JSX

What's the difference between the SUID (Stream Unique IDentifier) and the private static member serialVersionUID?Location: http://www.jguru.com/faq/view.jsp?EID=236482 Created: Oct 25, 2000 Modified: 2000-10-25 11:19:34.19Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question

Page 45: Serialization FAQ From jGuru

originally posed by Declan Shanaghy (http://www.jguru.com/guru/viewbio.jsp?EID=109967

The SUID is one of a number of things that the serialization protocol writes to the stream in addition to the serialized object (other things include a magic number and the fully- qualified class name of the object). SUID is not the same as the static variable serialVersionUID, although SUID is computed using that field, if it exists. In psuedocode,

if (serialVersionUID is defined) then SUID is set equal to serialVersionUIDelse SUID is computed algoritmicallyBecause serialVersionUID is a static member, it is not written to the stream as part of the serialized object. Instead, serialization uses the serialVersionUID to compute the SUID. The SUID is then sent to the stream as part of the stream protocol, not as part of the object definition.

Deserializing requires two things:

1. The serialized object. This does not include the static member serialVersionUID, but it does include the SUID, fully-qualified class name, etc.

2. The .class file. This does include the static members.

When deserializing, the SUID embedded in the object input stream is compared to the SUID computed from the local .class file according to the psuedocode above. If the SUIDs are equal, then the serialized object is compatible with the class file definition.

Are classes that implement Serializable required to have no-argument constructors?Location: http://www.jguru.com/faq/view.jsp?EID=251942 Created: Nov 12, 2000 Modified: 2000-12-21 16:46:34.173Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

No. This is a common misconception. The deserialization process does not use the object's constructor - the object is instantiated without a constructor and initialized using the serialized instance data. The only requirement on the constructor for a class that implements Serializable is that the first non-serializable superclass in its inheritence hierarchy must have a no-argument constructor. (See http://www.jguru.com/jguru/faq/view.jsp?EID=34802 for a more complete explanation). This makes sense: deserialization needs to reconstruct the entire object state, which includes the state of any superclasses. If the superclass is not itself serializable, then deserialization needs to instantiate that superclass from scratch - thus the requirement. For example, with the following class:

public class MySerializableClass implements Serializable { ...}you do not need a no-argument constructor. MySerializableClass meets all requirements because its first non-serializable superclass, Object, has a no-argument constructor. In the following example:

Page 46: Serialization FAQ From jGuru

public class MyFirstClass {}public class MySecondClass extends MyFirstClass implements Serializable { ...}MyFirstClass has the default, no-argument constructor, so no other constructor is needed. If, however, MyFirstClass defined constructors which accepted arguments without also explicitly declaring a no-argument constructor, then you would get a NotSerializableExceptin when trying to serialize MySecondClass.

All the requirements for an object that implements Serializable are listed at http://www.jguru.com/jguru/faq/view.jsp?EID=31434.

Comments and alternative answers

Throws java.io.InvalidClassException Author: G R (http://www.jguru.com/guru/viewbio.jsp?EID=999272), Sep 14, 2002Just wanted to correct that if the super class does not have a no argument constructor, then following exception is thrown when you try to deserialize the class. java.io.InvalidClassException: no valid constructor

Are there any limits on the size of a serialized object? Location: http://www.jguru.com/faq/view.jsp?EID=254140 Created: Nov 15, 2000 Modified: 2001-03-06 22:15:18.212Author: Dane Foster (http://www.jguru.com/guru/viewbio.jsp?EID=228595) Question originally posed by Raghu Konka (http://www.jguru.com/guru/viewbio.jsp?EID=235671

There are limits, but in practice you shouldn't encounter them. You are limited by the amount of memory your JVM can allocate to the creation and maintainence of your object. As for writing it out to disk, you are limited by the maximum file size of the underlying OS. Linux for example, has a 2GB limit on any one file.

See also:

http://www.jguru.com/jguru/faq/view.jsp?EID=28713

How can I determine the byte length of an object that I serialize to a stream?Location: http://www.jguru.com/faq/view.jsp?EID=264462 Created: Nov 28, 2000 Modified: 2001-01-17 20:50:49.845Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Alan Cox (http://www.jguru.com/guru/viewbio.jsp?EID=255589

There are a couple of things you can do. First, you can pipe the ObjectOutputStream into a ByteArrayOutputStream, then examine the length of the byte array:

ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream out = ObjectOutputStream(baos);out.writeObject(new MyObject());

Page 47: Serialization FAQ From jGuru

out.flush();//// Subtract 4 bytes from the length, because the serialization// magic number (2 bytes) and version number (2 bytes) are// both written to the stream before the object//int objectsize = baos.toByteArray().length - 4;System.out.println("MyObject occupies " + objectsize + " bytes when serialized");

Or, if you want to stream to a destination other than a byte array, you can write a subclass of DataOutputStream which allows you to access the protected variable written. This subclass can be used to monitor the data sent through the stream to any destination source:

import java.io.*;

public class ByteCounterOutputStream extends DataOutputStream { public ByteCounterOutputStream(OutputStream out) { super(out); }

public int bytesWrittenSoFar() { return written; }}To use this to write to a file and count the size of the objects written on-the-fly, you would do the following: FileOutputStream file = new FileOutputStream("junk");ByteCounterOutputStream bcos = new ByteCounterOutputStream(file);ObjectOutputStream out = new ObjectOutputStream(bcos);int start = bcos.bytesWrittenSoFar();out.writeObject(new MyObject());out.flush();int objectsize = bcos.bytesWrittenSoFar() - start;System.out.println("MyObject occupies " + objectsize + " bytes when serialized");

What is the role of serialization in EJB?Location: http://www.jguru.com/faq/view.jsp?EID=301817 Created: Jan 13, 2001 Modified: 2001-01-20 14:24:31.453Author: Tom McClure (http://www.jguru.com/guru/viewbio.jsp?EID=301803) Question originally posed by Laxmi bannai (http://www.jguru.com/guru/viewbio.jsp?EID=234299

A big part of EJB is that it is a framework for underlying RMI: remote method invocation. You're invoking methods remotely from JVM space 'A' on objects which are in JVM space 'B' -- possibly running on another machine on the network.

To make this happen, all arguments of each method call must have their current state plucked out of JVM 'A' memory, flattened into a byte stream which can be sent over a TCP/IP network connection, and then deserialized for reincarnation on the other end in JVM 'B' where the actual method call takes place.

Page 48: Serialization FAQ From jGuru

If the method has a return value, it is serialized up for streaming back to JVM A. Thus the requirement that all EJB methods arguments and return values must be serializable. The easiest way to do this is to make sure all your classes implement java.io.Serializable.

Comments and alternative answers

Yes, besides the answer above, I would like to add... Author: Mihir Kulkarni (http://www.jguru.com/guru/viewbio.jsp?EID=312865), Jan 25, 2001Yes, besides the answer above, I would like to add that: To save the state of a stateful session bean. The EJB container is a CTM and has to do efficient management of resources - as a result it has to passivate beans and use its resources optimally. The passivation strategy used commonly is Java serialization, of course, the strategy is vendor specific. The above discussion is relevant to the passivation of the stateful session beans wherein it is necessary to save the state of the stateful session bean when it is about to be passivated - ie, being disassociated from the EJBObject.

How to serialize large objects ? Author: Thomas Carrie (http://www.jguru.com/guru/viewbio.jsp?EID=499238), Oct 8, 2001What if I want to serialize a large object (a few Mb) and use it as a stream on the server side.

I think that serialization mechanism is not a good solution to that problem : it is slow (no // between network, client and server) and it uses a lot of memory.

Does anyone have a good solution to that problem ?

Re: How to serialize large objects ? Author: Sean Sullivan (http://www.jguru.com/guru/viewbio.jsp?EID=203382), May 8, 2002In EJB 2.0, you can use Local interfaces. The advantage: you can avoid object serialization for method calls within the same JVM

How can I instantiate a serialized JavaBean into an applet if my .ser file is in jar or zip archive?Location: http://www.jguru.com/faq/view.jsp?EID=312291 Created: Jan 25, 2001 Modified: 2001-01-25 11:24:26.095Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7) Question originally posed by Bartolomeo sorrentino (http://www.jguru.com/guru/viewbio.jsp?EID=234651

The Beans.instantiate() method needs to be passed the proper classloader. Just passing in null is not sufficient for an applet. For instance, if your class was Foo.class, use the following: Beans.instantiate(

Page 49: Serialization FAQ From jGuru

Foo.class.getClassLoader(),"Foo");Comments and alternative answers

instantiating serialized beans Author: Mark White (http://www.jguru.com/guru/viewbio.jsp?EID=1183797), Jul 5, 2004The posted answer is too terse. Is Foo the container class that is instantiating the bean or is it a class in the bean?

Re: instantiating serialized beans Author: kishor chandra (http://www.jguru.com/guru/viewbio.jsp?EID=1257473), Aug 12, 2005"Foo" is bean class(java bean name)

What is the correct order of ObjectInputStream/ObjectOutputStream creation on the client and the server when sending objects over a network connection? Location: http://www.jguru.com/faq/view.jsp?EID=333392 Created: Feb 19, 2001 Modified: 2001-08-18 18:55:36.37Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Joen Moreno (http://www.jguru.com/guru/viewbio.jsp?EID=134600

According to the API documentation for ObjectInputStream's constructor:

The stream header containing the magic number and version number are read from the stream and verified. This method will block until the corresponding ObjectOutputStream has written and flushed the header. This is a very important point to be aware of when trying to send objects in both directions over a socket because opening the streams in the wrong order will cause deadlock.

Consider for example what would happen if both client and server tried to construct an ObjectInputStream from a socket's input stream, prior to either constructing the corresponding ObjectOutputStream. The ObjectInputStream constructor on the client would block, waiting for the magic number and version number to arrive over the connection, while at the same time the ObjectInputStream constructor on the server side would also block for the same reason. Hence, deadlock.

Because of this, you should always make it a practice in your code to open the ObjectOutputStream and flush it first, before you open the ObjectInputStream. The ObjectOutputStream constructor will not block, and invoking flush() will force the magic number and version number to travel over the wire. If you follow this practice in both your client and server, you shouldn't have a problem with deadlock.

How can I serialize a JavaMail Message?Location: http://www.jguru.com/faq/view.jsp?EID=345906 Created: Mar 6, 2001 Modified: 2002-01-07 10:24:05.348Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7) Question originally posed by Eric Rapp (http://www.jguru.com/guru/viewbio.jsp?EID=345778

Page 50: Serialization FAQ From jGuru

You can't. As messages are associated with folders which are associated with sessions, Message objects are considered not serializable. Like threads and images you need to save the pieces that are not session-specific and regenerate the object at the other end. Save the contents to an RFC 822 formatted stream (message.writeTo()), serialize the bytes, and recreate the message at the other end.

Where can I learn (more) about Java's I/O (input/output, IO) capabilities? Location: http://www.jguru.com/faq/view.jsp?EID=431192 Created: May 30, 2001 Author: John Mitchell (http://www.jguru.com/guru/viewbio.jsp?EID=4)

Check out the jGuru IO FAQ.

Where can I learn (more) about Java's support asynchronous and publish/subscribe messaging using JMS (Java Message Service)? Location: http://www.jguru.com/faq/view.jsp?EID=431210 Created: May 30, 2001 Author: John Mitchell (http://www.jguru.com/guru/viewbio.jsp?EID=4)

Check out the jGuru JMS FAQ.

Where can I learn (more) about Java RMI (Remote Method Invocation)? Location: http://www.jguru.com/faq/view.jsp?EID=431242 Created: May 30, 2001 Author: John Mitchell (http://www.jguru.com/guru/viewbio.jsp?EID=4)

Check out the jGuru RMI FAQ.

What does the Serializable interface do?Location: http://www.jguru.com/faq/view.jsp?EID=454508 Created: Jul 13, 2001 Modified: 2001-07-13 15:01:10.018Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question originally posed by Ramamurthy K (http://www.jguru.com/guru/viewbio.jsp?EID=453334

Serializable is a tagging interface; it prescribes no methods. It serves to assign the Serializable data type to the tagged class and to identify the class as one which the developer has designed for persistence. ObjectOutputStream serializes only those objects which implement this interface. Please refer to http://www.jguru.com/faq/view.jsp?EID=31434 and the other Serialization FAQs for more information.Comments and alternative answers

How selectively serialize instance variables? Author: Pawan Singh (http://www.jguru.com/guru/viewbio.jsp?EID=1183152), Jul 1, 2004Please describe on how to serialize instance variables selectively. Most I know is that, "transient" keyword does this. I request to describe the underlying detail.

Re: How selectively serialize instance variables? Author: kishor chandra (http://www.jguru.com/guru/viewbio.jsp?

Page 51: Serialization FAQ From jGuru

EID=1257473), Aug 12, 2005transient is used when u have any sensitive data. like credit card number ,a/c num,etc. u can also use static variable if u dont want to sereilize the variable.

What's the serialver syntax to get the serialVersionUID of an array?Location: http://www.jguru.com/faq/view.jsp?EID=468625 Created: Aug 4, 2001 Modified: 2001-08-05 11:25:04.557Author: John Zukowski (http://www.jguru.com/guru/viewbio.jsp?EID=7)

You need to pass in the array "type" after the [ character, and before a ; character. If the type is a class, add the letter L and the fully qualified class name. If the type is a primitive, the type codes are specified in ObjectStreamField.getTypeCode(), you can almost just capitalize the first letter and place after [. Though, that isn't always the case. For boolean, use Z instead of B, for long use J since L is already taken for classes and interfaces.

For instance, for the String class the syntax is

serialver "[Ljava.lang.String;"For an array of int elements, it is: serialver "[I;"

How can i implement Serializable with my own Custom Data Format? Location: http://www.jguru.com/faq/view.jsp?EID=777322 Created: Feb 28, 2002 Author: Davanum Srinivas (http://www.jguru.com/guru/viewbio.jsp?EID=2011)

import java.io.*;public class CustomDataExample implements Serializable {

transient int dimension; transient int thearray[][];

/** * Create the triangular array of dimension dim and initialize it */ CustomDataExample (int dim) { dimension = dim; thearray = new int[dim][dim];

arrayInit(); }

/** * Create an CustomDataExample object, serialize it, deserialize it and * see that they are the same. So, basically test that this custom * data example's serialization works. */ public static void main(String args[]) {

CustomDataExample corg = new CustomDataExample(4);CustomDataExample cnew = null;

// Serialize the original class object

Page 52: Serialization FAQ From jGuru

try { FileOutputStream fo = new FileOutputStream("cde.tmp"); ObjectOutputStream so = new ObjectOutputStream(fo); so.writeObject(corg); so.flush(); so.close();} catch (Exception e) { e.printStackTrace(); System.exit(1);}

// Deserialize in to new class objecttry { FileInputStream fi = new FileInputStream("cde.tmp"); ObjectInputStream si = new ObjectInputStream(fi); cnew = (CustomDataExample) si.readObject();

si.close();} catch (Exception e) { e.printStackTrace(); System.exit(1);}

// Print out to check the correctnessSystem.out.println();System.out.println("Printing the original array...");System.out.println(corg);System.out.println();System.out.println("Printing the new array...");System.out.println(cnew);System.out.println();System.out.println("The original and new arrays should be the

same!");System.out.println();

} /** * Write out the dimension and 1/2 of the 2-dimensional array to the * ObjectOutputStream s. readObject depends on this data format. * * @serialData Write serializable fields, if any exist. * Write out the integer Dimension of the symetrical, * two-dimensional array. Write out the integers composing * 1/2 of the 2-dimensional array. * */ private void writeObject(ObjectOutputStream s)

throws IOException { // Call even if there is no default serializable fields. s.defaultWriteObject();

// save the dimension s.writeInt(dimension);

// write out only 1/2 of the 2-dimensional array for (int i = 0; i < dimension; i++) {

for (int j = 0; j <= i; j++) {

Page 53: Serialization FAQ From jGuru

s.writeInt(thearray[i][j]);}

} } /** * Read in the dimension and 1/2 of the 2-dimensional array from the * ObjectInputStream s. Was written to by writeObject. Also, copy the * 1/2 array to the other half to completely fill the symmetric array. * * @serialData Read serializable fields, if any exist. * Read optional data consisting of an integer indicating * both dimensions of the 2-dimensional array. Read in * 1/2 of the 2-dimensional array. */ private void readObject(ObjectInputStream s)

throws IOException, ClassNotFoundException { /* Call even if there is no default serializable fields. * Enables default serializable fields to be added in

future versions * and skipped by this version which has no default serializable fields.

*/ s.defaultReadObject();

// restore the dimension dimension = s.readInt(); // allocate space for the array thearray = new int[dimension][dimension]; // first restore 1/2 the 2-dimensional array for (int i = 0; i < dimension; i++) {

for (int j = 0; j <= i; j++) { thearray[i][j] = s.readInt();}

} // copy over to the other side for (int i = 0; i < dimension; i++) {

for (int j = dimension - 1; j > i; j--) { thearray[i][j] = thearray[j][i];}

} }

/** * Initialize the array to some numbers starting from 0 - make it * symmetrical */ void arrayInit() { int x = 0;

for (int i = 0; i < dimension; i++) { for (int j = 0; j <= i; j++) {

Page 54: Serialization FAQ From jGuru

thearray[i][j] = x;thearray[j][i] = x;x++;

}}

}

/** * Print the 2-dimensional array. Useful for testing. */ public String toString() {

StringBuffer sb = new StringBuffer();for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) {

sb.append(Integer.toString(thearray[i][j])+ " "); } sb.append("\n");}return(sb.toString());

}}Comments and alternative answers

I think implementing the java.io.Externalizable interface would be a more appropriate way of doing things Author: Gurdeep Singh (http://www.jguru.com/guru/viewbio.jsp?EID=1056522), Feb 13, 2003You can implement the writeExternal and readExternal methods of the java.io.Externalizable interface to customize the way the state of your class is saved

Re: I think implementing the java.io.Externalizable interface would be a more appropriate way of doing things Author: Deepak Nohwal (http://www.jguru.com/guru/viewbio.jsp?EID=1244603), May 18, 2005This always gets me confusing. What advantage can Externalizable give me which I can't receive from Serializable? I can always implement readObject() and writeObject() methods to over-ride default serialization. Then why should I use Externalizable? Any major reasons?

What is the easiest way to convert my java beans into xml?Location: http://www.jguru.com/faq/view.jsp?EID=818237 Created: Mar 30, 2002 Author: Davanum Srinivas (http://www.jguru.com/guru/viewbio.jsp?EID=2011)

Use java.beans.XMLEncoder. XMLEncoder e = new XMLEncoder( new BufferedOutputStream( new FileOutputStream("Test.xml")));e.writeObject(new JButton("Hello, world"));e.close();Comments and alternative answers

Page 55: Serialization FAQ From jGuru

Well.. with some oddities... Author: Rick Ross (http://www.jguru.com/guru/viewbio.jsp?EID=811906), Apr 12, 2002I noticed that any property that is not called explictly on the object seems to get left out of serialization. Uncommenting the two set methods in main() below will ensure that both properties (Number and Name) are stored in the xml. Leaving them commented out will produce xml that doesn't persist any fields.

I realize that Serialization is all about the current state of the object, and if the values haven't changed then re-creating the object will automatically preserve state.

It just seems like it would have been a bit more usefull to have XML that is a true descriptor of the object. R.

import java.beans.XMLEncoder;import java.io.*;

public class Test implements Serializable{ private int number = 5; private String s = "Test y"; public int getNumber() { return number; } public void setNumber(int i) { number = i; }

public String getName() { return s; } public void setName(String sn) { s = sn; }

public static void main (String args[]) { try { Test t = new Test(); // t.setNumber(21); // t.setName("jjhhhjj"); XMLEncoder e = new XMLEncoder( new BufferedOutputStream( new FileOutputStream("out.xml"))); e.writeObject(t); e.close(); } catch (Exception e) { e.printStackTrace(); } }}

Re: Well.. with some oddities... Author: Rama Konjeti (http://www.jguru.com/guru/viewbio.jsp?EID=1010789), Oct 10, 2002As per the java documentation, it doesn't try to store the default values. It is a

Page 56: Serialization FAQ From jGuru

feature, not a bug. For our application it shouldn't matter as long as the objects are same before and after serialization using XMLEncoder/XMLDecoder.

Re[2]: Another question relating to this topic Author: Chris Duran (http://www.jguru.com/guru/viewbio.jsp?EID=1100624), Jul 10, 2003I am trying to serialize a vector of object instances to XML but the encoder only saves the class names. Can you do this with the XMLEncoder?

Re[3]: Another question relating to this topic Author: Charlie Cho (http://www.jguru.com/guru/viewbio.jsp?EID=1134780), Dec 18, 2003Chris, I was just wondering if you got an answer to your question. You posted this question while back. If you are still searching for the answer let me know.

Re[2]: Well.. with some oddities... Author: Chris Duran (http://www.jguru.com/guru/viewbio.jsp?EID=1100624), Aug 6, 2004Does anyone know how to turn that "feature" off. I have a need to save all fields of the bean, even default values.

Also consider using other libraries such as XMLBean from apache Author: Anish Biswas (http://www.jguru.com/guru/viewbio.jsp?EID=1222664), Jan 22, 2005This is good. Try it.