Title: Serialization
1Serialization
- HY556 Distributed Systems
- Computer Science Department
- University of Crete
2What is Serialization
- The process of storing or retrieving information
through a standard protocol
3Object Serialization
- java.io
- ObjectInputStream
- ObjectOutputStream
- two streams special for reading/writing objects
- writing an object
- represent its state in a serialized form
sufficient to reconstruct the object as it is
read - (all object attributes, such as class name,
field name, access modifiers, have to be
preserved !)
4Use of Object Serialization
- RMI (Remote Method Invocation)
- communication between objects via sockets
- Lightweight persistence
- archival of an object for use in a later
invocation of the program - Object lifetime
- ? created by the new operator
- exists
- destroyed by the Java VMs garbage collector
when the program no longer holds a reference to
the object
5Serialization API
6Serialization API (cont.)
7Serialization API (cont.)
8Serialization API (cont.)
- The Serializable interface defines no methods but
is an indicator that the class is compatible with
serialization and may have private readObject()
and writeObject() methods to control
serialization. - Only the data in the objects and the declarations
of the classes are encoded in the byte stream
the Java VM bytecodes that implement the methods
of the classes are not stored when an object is
serialized. - When the object is retrieved from the stream, the
class declaration is read and the normal
class-loading mechanisms are used to load the
code. - If a matching class is not found, readObject()
throws ClassNotFoundException.
9Serializing Objects-writing
- Writing objects to a stream
-
-
- Gets the current time in milliseconds by
constructing a Date object and then serializes
that object. - ObjectOutputStream must be constructed on another
stream. - The writeObject method throws a
NotSerializableException if it's given an object
that is not serializable. - An object is serializable only if its class
implements the Serializable interface.
FileOutputStream out new FileOutputStream("theTi
me") ObjectOutputStream s new
ObjectOutputStream(out) s.writeObject("Today") s
.writeObject(new Date()) s.flush()
10Serializing Objects-reading
- Reading objects from a stream
-
- ObjectInputStream must be constructed on another
stream. - (Here, the objects were archived in a file,
so the code constructs an ObjectInputStream on
a FileInputStream.) - Use ObjectInputStream's readObject method to read
the String and the Date objects from the file. - The objects must be read from the stream in the
same order in which they were written. Note that
the return value from readObject is an object
that is cast to and assigned to a specific type.
FileInputStream in new FileInputStream("theTime"
) ObjectInputStream s new ObjectInputStream(in)
String today (String)s.readObject() Date
date (Date)s.readObject()
11Serializing Objects-Tricks
- Java I/O streams ? layered (as seen previously)
- ByteArrayOutputStream, another example
byte data null ByteArrayOutputStream b_outs
new ByteArrayOutputStream() ObjectOutputStream
obj_outs new ObjectOutputStream(b_outs)
12Serializing Objects-Tricks (cont.)
/ pstruct is an object containing fields of
different types, e.g. String, double,
etc./ obj_outs.writeObject(pstruct.product_id) o
bj_outs.writeObject(pstruct.product_name) obj_out
s.writeObject(pstruct.product_description) obj_ou
ts.writeObject(new Double(pstruct.price)) obj_out
s.writeObject(pstruct.currency) obj_outs.writeObj
ect(new Boolean(pstruct.soft_good_p)) obj_outs.wr
iteObject(new Boolean(pstruct.for_sale_p)) obj_ou
ts.writeObject(pstruct.terms_and_conditions) data
b_outs.toByteArray() obj_outs.close() b_outs.
close()
13Serializing Objects-Tricks (cont.)
/ at this point, byte buffer contains the
serialized form of pstruct / / reconstruct
pstruct as follows / ByteArrayInputStream b_ins
new ByteArrayInputStream(data) ObjectInputStrea
m obj_ins new ObjectInputStream(b_ins)
14Serializing Objects-Tricks (cont.)
String product_id (String)obj_ins.readObject()
String product_name (String)obj_ins.readObject()
String product_description (String)obj_ins.rea
dObject() double price ((Double)obj_ins.readObj
ect()).doubleValue() String currency
(String)obj_ins.readObject() boolean soft_good_p
((Boolean)obj_ins.readObject()).booleanValue()
boolean for_sale_p ((Boolean)obj_ins.readObject(
)).booleanValue() String terms_and_conditions
(String)obj_ins.readObject() b_ins.close() obj_i
ns.close() ProductStruct pstruct new
ProductStruct( ... )
15Serializing Objects-Tips
- Complication
- Correct handling of other referenced objects.
The object to be serialized must include a copy
of all the objects it references, all the objects
those objects reference, and so on. (All these
objects have to be included by the serialized
object, because they are part of its total
state.) - Note
- The writeObject() method does not explicitly
synchronize on the object being serialized. If
you have multiple threads using the same object,
and one thread can possibly be serializing an
object while another thread is manipulating
fields of the same object, you must take steps to
be thread safe (e.g. add explicitly
synchronization code, make an object clone before
serializing).
16Object Serialization for Classes
- Making instances of your classes serializable ?
- Just add the implements Serializable clause to
your class declaration -
- No methods needed (serialization is handled by
the defaultWriteObject method of
ObjectOutputStream). - Deserialization with the defaultReadObject method
in ObjectInputStream. - Default behavior is good enough, but can be slow,
and a class might want more explicit control over
the serialization.
public class MySerializableClass implements
Serializable ...
17Customizing Serialization
- Providing 2 methods (declared exactly as shown
here) - writeObject
- readObject
private void writeObject(ObjectOutputStream s)
throws IOException s.defaultWriteObject() //
if needed call only here !!! // customized
serialization code
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
s.defaultReadObject() // if needed call only
here !!! // customized deserialization
code ... // followed by code to update the
object, if necessary
18The Externalizable Interface
- Differs from Serializable in
- the amount of control in the serialization
process - the extent of of customizations
- writeObject, readObject ? responsible for
serializing only the immediate class. - Any serialization required by the superclasses is
handled automatically. - Class ? explicitly coordinate with its
superclasses to serialize itself ? implementing
the Externalizable interface. - Complete, explicit control of the
serialization process. - ! Only the class identification of the object
is automatically saved by the stream. The class
is responsible for writing and reading its
contents, and it must coordinate with its
superclasses to do so (whether or not the state
of superclasses and which fields are stored).
19Externalization API
- writeExternal() must encode the data of the
object in a form and sequence supported by
readExternal(). - Does not support code versioning ? you must
provide your own versioning approach. - Above methods are public ? security risk (a
client may be able to write or read information
in the object other than by using its methods).
20Protecting sensitive info
- During deserialization the private state of the
object is restored. - Avoid compromising a class
- sensitive state of an object must not be restored
from the stream - Sensitive state of an object must be refined by
the class - transient and static fields are not
serialized/deserialized - prevent state from appearing in the stream
- a classs transient fields are safe
- Particularly sensitive classes should not be
serialized ! - Beneficial for some classes allow writing and
reading but specifically handle and revalidate
the state during deserialization. - If access should be denied, throwing a
NotSerializableException will prevent further
access.
21Implementing Serializable Default Case
- import java.io.
- import java.net.
- import java.util.
- class AddressEntry implements Serializable
- String name
- String address
-
- public AddressEntry(String name, String address)
- if ((name null) (address null))
- throw new IllegalArgumentException()
- this.name name
- this.address address
-
22Default Case (cont.)
- public boolean equals(AddressEntry e)
- return (name.equalsIgnoreCase(e.name))
- (address.equalsIgnoreCase(e.address))
-
- // end class AddressEntry
- class AddressBook implements Serializable
- Hashtable table
- transient ServerSocket socket
23Default Case (cont.)
- public AddressBook()
- table new Hashtable()
- try
- socket new ServerSocket(2020)
-
- catch (IOException e)
- socket null
-
-
24Default Case (cont.)
- public AddressEntry lookup(String key)
- return (AddressEntry) table.get(key)
-
- public AddressEntry add(String key, AddressEntry
entry) - return (AddressEntry) table.put(key, entry)
-
- public int size()
- return table.size()
-
25Default Case (cont.)
- public boolean equals(AddressBook b)
- if ((b null) (size() ! b.size())) return
false - Enumeration keys table.keys()
- while (keys.hasMoreElements())
- String key (String)keys.nextElement()
- AddressEntry mine lookup(key)
- AddressEntry other b.lookup(key)
- if (!mine.equals(other)) return false
-
- return true
-
- // end class AddressBook
26Default Case (cont.)
- public class Example
- public static void main(String args)
- String fname addrbook2.out
- AddressEntry dave new AddressEntry(Dave,
Main Street) - AddressEntry tom new AddressEntry(Tom,
Second Street) - AddressBook addr new AddressBook()
- addr.add(Dave, dave)
- addr.add(Tom, tom)
- addr.add(Tommy, tom)
27Default Case (cont.)
- try
- FileOutputStream fout new FileOutputStream(fn
ame) - ObjectOutputStream out new
ObjectOutputStream(fout) - out.writeObject(addr)
- out.close()
- FileInputStream fin new FileInputStream(fname
) - ObjectInputStream in new ObjectInputStream(fi
n) - AddressBook copy (AddressBook)
in.readObject() -
28Default Case (cont.)
- if (copy.lookup(Tom) ! copy.lookup(Tommy))
- System.out.println(Multiple keys to object
not restored) - if (addr.equals(copy))
- System.out.println(Objects are equal)
- else System.out.println(Objects are
different) - // end try
- catch (Exception e)
- e.printStackTrace(System.out)
-
- // end main
- // end class Example
29Implementing Serializable Customized Case
- / This example uses the same AddressEntry class
as defined previously / - class AddressBook implements Serializable
- transient Hashtable table
-
- / This class has the same constructor,
lookup(), add(), size() and - equals() methods as defined previously.
- BUT
- Does not automatically serialize the
hashtable. - Methods writeObject(), readObject() are
overridden - to provide a custom serial format for our
AddressBook. /
30Customized Case (cont.)
- private void writeObject(ObjectOutputStream out)
throws IOException - out.writeInt(table.size())
- Enumeration enum (Enumeration) table.keys()
- while (enum.hasMoreElements())
- String key (String) enum.nextElement()
- AddressEntry entry (AddressEntry)
table.get(key) - out.writeObject(key)
- out.writeObject(entry)
-
-
31Customized Case (cont.)
- / At restoration time, object has been created
but instance variables notinitialized / - private void readObject(ObjectInputStream in)
- throws IOException, ClassNotFoundException
- table new Hashtable()
- for (int count in.readInt() count gt 0
count--) - String key (String) in.readObject()
- AddressEntry (AddressEntry) in.readObject()
- if ((entry.name null) (entry.address
null)) - throw new InvalidObjectException(name and
address - fields must be non-null)
- table.put(key, entry)
-
-
- // end class AddressBook