Sie sind auf Seite 1von 57

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.

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, 2004
This 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.

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.

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,
2002
Is 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, 2002
The 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
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.
• 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, 2000
Do 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, 2002
In 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.
• 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, 2002
Hello, 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, 2002
Using 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.766
Author: 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, 2000
You 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, 2000
Compatibility between Java versions is discussed in the FAQ found at
http://www.jguru.com/jguru/faq/view.jsp?EID=13165

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.046
Author: 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.655
Author: 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:

• 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)


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;
}

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()
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,
2002
It 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, 2004
I 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.249
Author: 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

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.884
Author: 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.342
Author: 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
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.197
Author: 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.722
Author: 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.

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_MAGIC
0x0005 // ObjectStreamContents.STREAM_VERSION
0x77 // ObjectStreamContents.TC_BLOCKDATA
0x01 // length of data
0x41 // 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.871
Author: 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.

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.984
Author: 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.241
Author: 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.108
Author: 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, 2002
According 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
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.294
Author: 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.955
Author: 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, 2002
In encountered the following problem recently. Is this related to the limitation?

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.6
Author: 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.132
Author: 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
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.913
Author: 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.837
Author: 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.694
Author: 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.577
Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10)

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.157
Author: 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()) {
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
//
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.775
Author: 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.

/**
* 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));
}
}
}

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.17
Author: 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
Created: Apr 11, 2000 Modified: 2000-04-11 11:17:31.513
Author: 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.926
Author: 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.803
Author: 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.

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.014
Author: 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.951
Author: 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.083
Author: 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-description


The 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
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.652
Author: 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.904
Author: 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.552
Author: 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.

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,
2001
Externalization 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.933
Author: 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,
2000
Is 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.566
Author: 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
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.403
Author: 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.974
Author: 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;

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.317
Author: 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
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.876
Author: 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.035
Author: 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, 2001
When 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.

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.879
Author: 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.342
Author: 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.
• 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.258
Author: 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, 2002
You 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, 2002
Open source, GPL implementation from com.Ostermiller.util:
http://ostermiller.org/utils/Base64.html
It 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/
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.html
http://mindprod.com/products.html#BASE64
Encodes from byte arrays to strings, decodes from strings to byte arrays.

Open source, GPL implementation by Kevin Kelley:


http://kevinkelley.mystarband.net/java/goodies.html
Encodes and decodes from byte arrays to byte arrays.

Open source, freeware (any purpose with attribution) by Bob Withers:


http://www.ruffboy.com/download.htm
Encodes 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.html
Supports 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.431
Author: 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.

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, 2001
I 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.667
Author: 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.

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.512
Author: 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">
<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.927
Author: 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.922
Author: 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 {

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.706
Author: 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


"[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.056
Author: 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.397
Author: 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.624
Author: 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
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.022
Author: 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.23
Author: 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
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.376
Author: 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
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.05
Author: 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,
2004
I 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.803
Author: 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.646
Author: 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, 2000
Serialization 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.

Re: Serialization is for saving the state of an object...


Author: krishna raj (http://www.jguru.com/guru/viewbio.jsp?EID=1180669), Jun
22, 2004
But 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.631
Author: 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:

http://www.jguru.com/jguru/faq/view.jsp?EID=3419
and
http://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.577
Author: 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, 2000
You 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, 2001
Use 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.19
Author: Tim Rohaly (http://www.jguru.com/guru/viewbio.jsp?EID=10) Question
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 serialVersionUID
else
SUID is computed algoritmically
Because 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.173
Author: 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:
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, 2002
Just 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.212
Author: 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.845
Author: 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());
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.453
Author: 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.

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, 2001
Yes, 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, 2001
What 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, 2002
In 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.095
Author: 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(
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,
2004
The 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.37
Author: 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.348
Author: 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

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.018
Author: 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,
2004
Please 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?EID=1257473),
Aug 12, 2005
transient 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.557
Author: 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


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 object


try {
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 correctness


System.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++) {
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++) {
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, 2003
You 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, 2005
This 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

Well.. with some oddities...


Author: Rick Ross (http://www.jguru.com/guru/viewbio.jsp?EID=811906), Apr 12,
2002
I 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, 2002
As per the java documentation, it doesn't try to store the default values. It is a
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, 2003
I 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, 2003
Chris, 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, 2004
Does 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, 2005
This is good. Try it.

Das könnte Ihnen auch gefallen