44787
|
1 |
---
|
|
2 |
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
|
3 |
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
#
|
|
5 |
# This code is free software; you can redistribute it and/or modify it
|
|
6 |
# under the terms of the GNU General Public License version 2 only, as
|
|
7 |
# published by the Free Software Foundation.
|
|
8 |
#
|
|
9 |
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 |
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 |
# version 2 for more details (a copy is included in the LICENSE file that
|
|
13 |
# accompanied this code).
|
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU General Public License version
|
|
16 |
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 |
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 |
#
|
|
19 |
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
20 |
# or visit www.oracle.com if you need additional information or have any
|
|
21 |
# questions.
|
|
22 |
|
|
23 |
include-before: '[CONTENTS](index.html) | [PREV](changelog.html) | [NEXT](output.html)'
|
|
24 |
include-after: '[CONTENTS](index.html) | [PREV](changelog.html) | [NEXT](output.html)'
|
|
25 |
|
|
26 |
title: 'Java Object Serialization Specification: 1 - System Architecture'
|
|
27 |
---
|
|
28 |
|
|
29 |
- [Overview](#overview)
|
|
30 |
- [Writing to an Object Stream](#writing-to-an-object-stream)
|
|
31 |
- [Reading from an Object Stream](#reading-from-an-object-stream)
|
|
32 |
- [Object Streams as Containers](#object-streams-as-containers)
|
|
33 |
- [Defining Serializable Fields for a
|
|
34 |
Class](#defining-serializable-fields-for-a-class)
|
|
35 |
- [Documenting Serializable Fields and Data for a
|
|
36 |
Class](#documenting-serializable-fields-and-data-for-a-class)
|
|
37 |
- [Accessing Serializable Fields of a
|
|
38 |
Class](#accessing-serializable-fields-of-a-class)
|
|
39 |
- [The ObjectOutput Interface](#the-objectoutput-interface)
|
|
40 |
- [The ObjectInput Interface](#the-objectinput-interface)
|
|
41 |
- [The Serializable Interface](#the-serializable-interface)
|
|
42 |
- [The Externalizable Interface](#the-externalizable-interface)
|
|
43 |
- [Serialization of Enum Constants](#serialization-of-enum-constants)
|
|
44 |
- [Protecting Sensitive Information](#protecting-sensitive-information)
|
|
45 |
|
|
46 |
-------------------------------------------------------------------------------
|
|
47 |
|
|
48 |
## 1.1 Overview
|
|
49 |
|
|
50 |
The ability to store and retrieve Java^TM^ objects is essential to building all
|
|
51 |
but the most transient applications. The key to storing and retrieving objects
|
|
52 |
in a serialized form is representing the state of objects sufficient to
|
|
53 |
reconstruct the object(s). Objects to be saved in the stream may support either
|
|
54 |
the `Serializable` or the `Externalizable` interface. For Java^TM^ objects, the
|
|
55 |
serialized form must be able to identify and verify the Java^TM^ class from
|
|
56 |
which the contents of the object were saved and to restore the contents to a
|
|
57 |
new instance. For serializable objects, the stream includes sufficient
|
|
58 |
information to restore the fields in the stream to a compatible version of the
|
|
59 |
class. For Externalizable objects, the class is solely responsible for the
|
|
60 |
external format of its contents.
|
|
61 |
|
|
62 |
Objects to be stored and retrieved frequently refer to other objects. Those
|
|
63 |
other objects must be stored and retrieved at the same time to maintain the
|
|
64 |
relationships between the objects. When an object is stored, all of the objects
|
|
65 |
that are reachable from that object are stored as well.
|
|
66 |
|
|
67 |
The goals for serializing Java^TM^ objects are to:
|
|
68 |
|
|
69 |
- Have a simple yet extensible mechanism.
|
|
70 |
- Maintain the Java^TM^ object type and safety properties in the serialized
|
|
71 |
form.
|
|
72 |
- Be extensible to support marshaling and unmarshaling as needed for remote
|
|
73 |
objects.
|
|
74 |
- Be extensible to support simple persistence of Java^TM^ objects.
|
|
75 |
- Require per class implementation only for customization.
|
|
76 |
- Allow the object to define its external format.
|
|
77 |
|
|
78 |
## 1.2 Writing to an Object Stream
|
|
79 |
|
|
80 |
Writing objects and primitives to a stream is a straightforward process. For
|
|
81 |
example:
|
|
82 |
|
|
83 |
```
|
|
84 |
// Serialize today's date to a file.
|
|
85 |
FileOutputStream f = new FileOutputStream("tmp");
|
|
86 |
ObjectOutput s = new ObjectOutputStream(f);
|
|
87 |
s.writeObject("Today");
|
|
88 |
s.writeObject(new Date());
|
|
89 |
s.flush();
|
|
90 |
```
|
|
91 |
|
|
92 |
First an `OutputStream`, in this case a `FileOutputStream`, is needed to
|
|
93 |
receive the bytes. Then an `ObjectOutputStream` is created that writes to the
|
|
94 |
`FileOutputStream`. Next, the string "Today" and a Date object are written to
|
|
95 |
the stream. More generally, objects are written with the `writeObject` method
|
|
96 |
and primitives are written to the stream with the methods of `DataOutput`.
|
|
97 |
|
|
98 |
The `writeObject` method (see [Section 2.3, "The writeObject
|
|
99 |
Method"](output.html#the-writeobject-method)) serializes the specified object
|
|
100 |
and traverses its references to other objects in the object graph recursively
|
|
101 |
to create a complete serialized representation of the graph. Within a stream,
|
|
102 |
the first reference to any object results in the object being serialized or
|
|
103 |
externalized and the assignment of a handle for that object. Subsequent
|
|
104 |
references to that object are encoded as the handle. Using object handles
|
|
105 |
preserves sharing and circular references that occur naturally in object
|
|
106 |
graphs. Subsequent references to an object use only the handle allowing a very
|
|
107 |
compact representation.
|
|
108 |
|
|
109 |
Special handling is required for arrays, enum constants, and objects of type
|
|
110 |
`Class`, `ObjectStreamClass`, and `String`. Other objects must implement either
|
|
111 |
the `Serializable` or the `Externalizable` interface to be saved in or restored
|
|
112 |
from a stream.
|
|
113 |
|
|
114 |
Primitive data types are written to the stream with the methods in the
|
|
115 |
`DataOutput` interface, such as `writeInt`, `writeFloat`, or `writeUTF`.
|
|
116 |
Individual bytes and arrays of bytes are written with the methods of
|
|
117 |
`OutputStream`. Except for serializable fields, primitive data is written to
|
|
118 |
the stream in block-data records, with each record prefixed by a marker and an
|
|
119 |
indication of the number of bytes in the record.
|
|
120 |
|
|
121 |
`ObjectOutputStream` can be extended to customize the information about classes
|
|
122 |
in the stream or to replace objects to be serialized. Refer to the
|
|
123 |
`annotateClass` and `replaceObject` method descriptions for details.
|
|
124 |
|
|
125 |
## 1.3 Reading from an Object Stream
|
|
126 |
|
|
127 |
Reading an object from a stream, like writing, is straightforward:
|
|
128 |
|
|
129 |
```
|
|
130 |
// Deserialize a string and date from a file.
|
|
131 |
FileInputStream in = new FileInputStream("tmp");
|
|
132 |
ObjectInputStream s = new ObjectInputStream(in);
|
|
133 |
String today = (String)s.readObject();
|
|
134 |
Date date = (Date)s.readObject();
|
|
135 |
```
|
|
136 |
|
|
137 |
First an `InputStream`, in this case a `FileInputStream`, is needed as the
|
|
138 |
source stream. Then an `ObjectInputStream` is created that reads from the
|
|
139 |
`InputStream`. Next, the string "Today" and a Date object are read from the
|
|
140 |
stream. Generally, objects are read with the `readObject` method and primitives
|
|
141 |
are read from the stream with the methods of `DataInput`.
|
|
142 |
|
|
143 |
The `readObject` method deserializes the next object in the stream and
|
|
144 |
traverses its references to other objects recursively to create the complete
|
|
145 |
graph of objects serialized.
|
|
146 |
|
|
147 |
Primitive data types are read from the stream with the methods in the
|
|
148 |
`DataInput` interface, such as `readInt`, `readFloat`, or `readUTF`. Individual
|
|
149 |
bytes and arrays of bytes are read with the methods of `InputStream`. Except
|
|
150 |
for serializable fields, primitive data is read from block-data records.
|
|
151 |
|
|
152 |
`ObjectInputStream` can be extended to utilize customized information in the
|
|
153 |
stream about classes or to replace objects that have been deserialized. Refer
|
|
154 |
to the `resolveClass` and `resolveObject` method descriptions for details.
|
|
155 |
|
|
156 |
## 1.4 Object Streams as Containers
|
|
157 |
|
|
158 |
Object Serialization produces and consumes a stream of bytes that contain one
|
|
159 |
or more primitives and objects. The objects written to the stream, in turn,
|
|
160 |
refer to other objects, which are also represented in the stream. Object
|
|
161 |
Serialization produces just one stream format that encodes and stores the
|
|
162 |
contained objects.
|
|
163 |
|
|
164 |
Each object that acts as a container implements an interface which allows
|
|
165 |
primitives and objects to be stored in or retrieved from it. These interfaces
|
|
166 |
are the `ObjectOutput` and `ObjectInput` interfaces which:
|
|
167 |
|
|
168 |
- Provide a stream to write to and to read from
|
|
169 |
- Handle requests to write primitive types and objects to the stream
|
|
170 |
- Handle requests to read primitive types and objects from the stream
|
|
171 |
|
|
172 |
Each object which is to be stored in a stream must explicitly allow itself to
|
|
173 |
be stored and must implement the protocols needed to save and restore its
|
|
174 |
state. Object Serialization defines two such protocols. The protocols allow the
|
|
175 |
container to ask the object to write and read its state.
|
|
176 |
|
|
177 |
To be stored in an Object Stream, each object must implement either the
|
|
178 |
`Serializable` or the `Externalizable` interface:
|
|
179 |
|
|
180 |
- For a `Serializable` class, Object Serialization can automatically save and
|
|
181 |
restore fields of each class of an object and automatically handle classes
|
|
182 |
that evolve by adding fields or supertypes. A serializable class can
|
|
183 |
declare which of its fields are saved or restored, and write and read
|
|
184 |
optional values and objects.
|
|
185 |
|
|
186 |
- For an `Externalizable` class, Object Serialization delegates to the class
|
|
187 |
complete control over its external format and how the state of the
|
|
188 |
supertype(s) is saved and restored.
|
|
189 |
|
|
190 |
## 1.5 Defining Serializable Fields for a Class
|
|
191 |
|
|
192 |
The serializable fields of a class can be defined two different ways. Default
|
|
193 |
serializable fields of a class are defined to be the non-transient and
|
|
194 |
non-static fields. This default computation can be overridden by declaring a
|
|
195 |
special field in the `Serializable` class, `serialPersistentFields`. This field
|
|
196 |
must be initialized with an array of `ObjectStreamField` objects that list the
|
|
197 |
names and types of the serializable fields. The modifiers for the field are
|
|
198 |
required to be private, static, and final. If the field's value is null or is
|
|
199 |
otherwise not an instance of `ObjectStreamField[]`, or if the field does not
|
|
200 |
have the required modifiers, then the behavior is as if the field were not
|
|
201 |
declared at all.
|
|
202 |
|
|
203 |
For example, the following declaration duplicates the default behavior.
|
|
204 |
|
|
205 |
```
|
|
206 |
class List implements Serializable {
|
|
207 |
List next;
|
|
208 |
|
|
209 |
private static final ObjectStreamField[] serialPersistentFields
|
|
210 |
= {new ObjectStreamField("next", List.class)};
|
|
211 |
|
|
212 |
}
|
|
213 |
```
|
|
214 |
|
|
215 |
By using `serialPersistentFields` to define the Serializable fields for a
|
|
216 |
class, there no longer is a limitation that a serializable field must be a
|
|
217 |
field within the current definition of the `Serializable` class. The
|
|
218 |
`writeObject` and `readObject` methods of the `Serializable` class can map the
|
|
219 |
current implementation of the class to the serializable fields of the class
|
|
220 |
using the interface that is described in [Section 1.7, "Accessing Serializable
|
|
221 |
Fields of a Class"](#accessing-serializable-fields-of-a-class). Therefore, the
|
|
222 |
fields for a `Serializable` class can change in a later release, as long as it
|
|
223 |
maintains the mapping back to its Serializable fields that must remain
|
|
224 |
compatible across release boundaries.
|
|
225 |
|
|
226 |
**Note:** There is, however, a limitation to the use of this mechanism to
|
|
227 |
specify serializable fields for inner classes. Inner classes can only contain
|
|
228 |
final static fields that are initialized to constants or expressions built up
|
|
229 |
from constants. Consequently, it is not possible to set
|
|
230 |
`serialPersistentFields` for an inner class (though it is possible to set it
|
|
231 |
for static member classes). For other restrictions pertaining to serialization
|
|
232 |
of inner class instances, see section [Section 1.10, "The Serializable
|
|
233 |
Interface"](#the-serializable-interface).
|
|
234 |
|
|
235 |
## 1.6 Documenting Serializable Fields and Data for a Class
|
|
236 |
|
|
237 |
It is important to document the serializable state of a class to enable
|
|
238 |
interoperability with alternative implementations of a Serializable class and
|
|
239 |
to document class evolution. Documenting a serializable field gives one a final
|
|
240 |
opportunity to review whether or not the field should be serializable. The
|
|
241 |
serialization javadoc tags, `@serial`, `@serialField`, and `@serialData`,
|
|
242 |
provide a way to document the serialized form for a Serializable class within
|
|
243 |
the source code.
|
|
244 |
|
|
245 |
- The `@serial` tag should be placed in the javadoc comment for a default
|
|
246 |
serializable field. The syntax is as follows: `@serial` *field-description*
|
|
247 |
The optional *field-description* describes the meaning of the field and its
|
|
248 |
acceptable values. The *field-description* can span multiple lines. When a
|
|
249 |
field is added after the initial release, a *@since* tag indicates the
|
|
250 |
version the field was added. The *field-description* for `@serial` provides
|
|
251 |
serialization-specific documentation and is appended to the javadoc comment
|
|
252 |
for the field within the serialized form documentation.
|
|
253 |
|
|
254 |
- The `@serialField` tag is used to document an `ObjectStreamField` component
|
|
255 |
of a `serialPersistentFields` array. One of these tags should be used for
|
|
256 |
each `ObjectStreamField` component. The syntax is as follows:
|
|
257 |
`@serialField` *field-name field-type field-description*
|
|
258 |
|
|
259 |
- The `@serialData` tag describes the sequences and types of data written or
|
|
260 |
read. The tag describes the sequence and type of optional data written by
|
|
261 |
`writeObject` or all data written by the `Externalizable.writeExternal`
|
|
262 |
method. The syntax is as follows: `@serialData` *data-description*
|
|
263 |
|
|
264 |
The javadoc application recognizes the serialization javadoc tags and generates
|
|
265 |
a specification for each Serializable and Externalizable class. See [Section
|
|
266 |
C.1, "Example Alternate Implementation of
|
|
267 |
java.io.File"](examples.html#c.1-example-alternate-implementation-of-java.io.file)
|
|
268 |
for an example that uses these tags.
|
|
269 |
|
|
270 |
When a class is declared Serializable, the serializable state of the object is
|
|
271 |
defined by serializable fields (by name and type) plus optional data. Optional
|
|
272 |
data can only be written explicitly by the `writeObject` method of a
|
|
273 |
`Serializable` class. Optional data can be read by the `Serializable` class'
|
|
274 |
`readObject` method or serialization will skip unread optional data.
|
|
275 |
|
|
276 |
When a class is declared Externalizable, the data that is written to the stream
|
|
277 |
by the class itself defines the serialized state. The class must specify the
|
|
278 |
order, types, and meaning of each datum that is written to the stream. The
|
|
279 |
class must handle its own evolution, so that it can continue to read data
|
|
280 |
written by and write data that can be read by previous versions. The class must
|
|
281 |
coordinate with the superclass when saving and restoring data. The location of
|
|
282 |
the superclasses data in the stream must be specified.
|
|
283 |
|
|
284 |
The designer of a Serializable class must ensure that the information saved for
|
|
285 |
the class is appropriate for persistence and follows the
|
|
286 |
serialization-specified rules for interoperability and evolution. Class
|
|
287 |
evolution is explained in greater detail in [Chapter
|
|
288 |
5](version.html#versioning-of-serializable-objects), "Versioning of
|
|
289 |
Serializable Objects".
|
|
290 |
|
|
291 |
## 1.7 Accessing Serializable Fields of a Class
|
|
292 |
|
|
293 |
Serialization provides two mechanisms for accessing the serializable fields in
|
|
294 |
a stream:
|
|
295 |
|
|
296 |
- The default mechanism requires no customization
|
|
297 |
- The Serializable Fields API allows a class to explicitly access/set the
|
|
298 |
serializable fields by name and type
|
|
299 |
|
|
300 |
The default mechanism is used automatically when reading or writing objects
|
|
301 |
that implement the `Serializable` interface and do no further customization.
|
|
302 |
The serializable fields are mapped to the corresponding fields of the class and
|
|
303 |
values are either written to the stream from those fields or are read in and
|
|
304 |
assigned respectively. If the class provides `writeObject` and `readObject`
|
|
305 |
methods, the default mechanism can be invoked by calling `defaultWriteObject`
|
|
306 |
and `defaultReadObject`. When the `writeObject` and `readObject` methods are
|
|
307 |
implemented, the class has an opportunity to modify the serializable field
|
|
308 |
values before they are written or after they are read.
|
|
309 |
|
|
310 |
When the default mechanism cannot be used, the serializable class can use the
|
|
311 |
`putFields` method of `ObjectOutputStream` to put the values for the
|
|
312 |
serializable fields into the stream. The `writeFields` method of
|
|
313 |
`ObjectOutputStream` puts the values in the correct order, then writes them to
|
|
314 |
the stream using the existing protocol for serialization. Correspondingly, the
|
|
315 |
`readFields` method of `ObjectInputStream` reads the values from the stream and
|
|
316 |
makes them available to the class by name in any order. See [Section 2.2, "The
|
|
317 |
ObjectOutputStream.PutField
|
|
318 |
Class"](output.html#the-objectoutputstream.putfield-class) and [Section 3.2,
|
|
319 |
"The ObjectInputStream.GetField
|
|
320 |
Class"](input.html#the-objectinputstream.getfield-class) for a detailed
|
|
321 |
description of the Serializable Fields API.
|
|
322 |
|
|
323 |
## 1.8 The ObjectOutput Interface
|
|
324 |
|
|
325 |
The `ObjectOutput` interface provides an abstract, stream-based interface to
|
|
326 |
object storage. It extends the DataOutput interface so those methods can be
|
|
327 |
used for writing primitive data types. Objects that implement this interface
|
|
328 |
can be used to store primitives and objects.
|
|
329 |
|
|
330 |
```
|
|
331 |
package java.io;
|
|
332 |
|
|
333 |
public interface ObjectOutput extends DataOutput
|
|
334 |
{
|
|
335 |
public void writeObject(Object obj) throws IOException;
|
|
336 |
public void write(int b) throws IOException;
|
|
337 |
public void write(byte b[]) throws IOException;
|
|
338 |
public void write(byte b[], int off, int len) throws IOException;
|
|
339 |
public void flush() throws IOException;
|
|
340 |
public void close() throws IOException;
|
|
341 |
}
|
|
342 |
```
|
|
343 |
|
|
344 |
`The` `writeObject` method is used to write an object. The exceptions thrown
|
|
345 |
reflect errors while accessing the object or its fields, or exceptions that
|
|
346 |
occur in writing to storage. If any exception is thrown, the underlying storage
|
|
347 |
may be corrupted. If this occurs, refer to the object that is implementing this
|
|
348 |
interface for more information.
|
|
349 |
|
|
350 |
## 1.9 The ObjectInput Interface
|
|
351 |
|
|
352 |
The `ObjectInput` interface provides an abstract stream based interface to
|
|
353 |
object retrieval. It extends the `DataInput` interface so those methods for
|
|
354 |
reading primitive data types are accessible in this interface.
|
|
355 |
|
|
356 |
```
|
|
357 |
package java.io;
|
|
358 |
|
|
359 |
public interface ObjectInput extends DataInput
|
|
360 |
{
|
|
361 |
public Object readObject()
|
|
362 |
throws ClassNotFoundException, IOException;
|
|
363 |
public int read() throws IOException;
|
|
364 |
public int read(byte b[]) throws IOException;
|
|
365 |
public int read(byte b[], int off, int len) throws IOException;
|
|
366 |
public long skip(long n) throws IOException;
|
|
367 |
public int available() throws IOException;
|
|
368 |
public void close() throws IOException;
|
|
369 |
}
|
|
370 |
```
|
|
371 |
|
|
372 |
The `readObject` method is used to read and return an object. The exceptions
|
|
373 |
thrown reflect errors while accessing the objects or its fields or exceptions
|
|
374 |
that occur in reading from the storage. If any exception is thrown, the
|
|
375 |
underlying storage may be corrupted. If this occurs, refer to the object
|
|
376 |
implementing this interface for additional information.
|
|
377 |
|
|
378 |
## 1.10 The Serializable Interface
|
|
379 |
|
|
380 |
Object Serialization produces a stream with information about the Java^TM^
|
|
381 |
classes for the objects which are being saved. For serializable objects,
|
|
382 |
sufficient information is kept to restore those objects even if a different
|
|
383 |
(but compatible) version of the implementation of the class is present. The
|
|
384 |
`Serializable` interface is defined to identify classes which implement the
|
|
385 |
serializable protocol:
|
|
386 |
|
|
387 |
```
|
|
388 |
package java.io;
|
|
389 |
|
|
390 |
public interface Serializable {};
|
|
391 |
```
|
|
392 |
|
|
393 |
A Serializable class must do the following:
|
|
394 |
|
|
395 |
- Implement the `java.io.Serializable` interface
|
|
396 |
|
|
397 |
- Identify the fields that should be serializable
|
|
398 |
|
|
399 |
(Use the `serialPersistentFields` member to explicitly declare them
|
|
400 |
serializable or use the transient keyword to denote nonserializable
|
|
401 |
fields.)
|
|
402 |
|
|
403 |
- Have access to the no-arg constructor of its first nonserializable
|
|
404 |
superclass
|
|
405 |
|
|
406 |
The class can optionally define the following methods:
|
|
407 |
|
|
408 |
- A `writeObject` method to control what information is saved or to append
|
|
409 |
additional information to the stream
|
|
410 |
|
|
411 |
- A `readObject` method either to read the information written by the
|
|
412 |
corresponding `writeObject` method or to update the state of the object
|
|
413 |
after it has been restored
|
|
414 |
|
|
415 |
- A `writeReplace` method to allow a class to nominate a replacement object
|
|
416 |
to be written to the stream
|
|
417 |
|
|
418 |
(See [Section 2.5, "The writeReplace
|
|
419 |
Method"](output.html#the-writereplace-method) for additional information.)
|
|
420 |
|
|
421 |
- A `readResolve` method to allow a class to designate a replacement object
|
|
422 |
for the object just read from the stream
|
|
423 |
|
|
424 |
(See [Section 3.7, "The readResolve
|
|
425 |
Method](input.html#the-readresolve-method) for additional information.)
|
|
426 |
|
|
427 |
`ObjectOutputStream` and `ObjectInputStream` allow the serializable classes on
|
|
428 |
which they operate to evolve (allow changes to the classes that are compatible
|
|
429 |
with the earlier versions of the classes). See [Section 5.5, "Compatible Java
|
|
430 |
Type Evolution"](version.html#compatible-java-type-evolution) for information
|
|
431 |
about the mechanism which is used to allow compatible changes.
|
|
432 |
|
|
433 |
**Note:** Serialization of inner classes (i.e., nested classes that are not
|
|
434 |
static member classes), including local and anonymous classes, is strongly
|
|
435 |
discouraged for several reasons. Because inner classes declared in non-static
|
|
436 |
contexts contain implicit non-transient references to enclosing class
|
|
437 |
instances, serializing such an inner class instance will result in
|
|
438 |
serialization of its associated outer class instance as well. Synthetic fields
|
|
439 |
generated by `javac` (or other Java^TM^ compilers) to implement inner classes
|
|
440 |
are implementation dependent and may vary between compilers; differences in
|
|
441 |
such fields can disrupt compatibility as well as result in conflicting default
|
|
442 |
`serialVersionUID` values. The names assigned to local and anonymous inner
|
|
443 |
classes are also implementation dependent and may differ between compilers.
|
|
444 |
Since inner classes cannot declare static members other than compile-time
|
|
445 |
constant fields, they cannot use the `serialPersistentFields` mechanism to
|
|
446 |
designate serializable fields. Finally, because inner classes associated with
|
|
447 |
outer instances do not have zero-argument constructors (constructors of such
|
|
448 |
inner classes implicitly accept the enclosing instance as a prepended
|
|
449 |
parameter), they cannot implement `Externalizable`. None of the issues listed
|
|
450 |
above, however, apply to static member classes.
|
|
451 |
|
|
452 |
## 1.11 The Externalizable Interface
|
|
453 |
|
|
454 |
For Externalizable objects, only the identity of the class of the object is
|
|
455 |
saved by the container; the class must save and restore the contents. The
|
|
456 |
`Externalizable` interface is defined as follows:
|
|
457 |
|
|
458 |
```
|
|
459 |
package java.io;
|
|
460 |
|
|
461 |
public interface Externalizable extends Serializable
|
|
462 |
{
|
|
463 |
public void writeExternal(ObjectOutput out)
|
|
464 |
throws IOException;
|
|
465 |
|
|
466 |
public void readExternal(ObjectInput in)
|
|
467 |
throws IOException, java.lang.ClassNotFoundException;
|
|
468 |
}
|
|
469 |
```
|
|
470 |
|
|
471 |
The class of an Externalizable object must do the following:
|
|
472 |
|
|
473 |
- Implement the `java.io.Externalizable` interface
|
|
474 |
|
|
475 |
- Implement a `writeExternal` method to save the state of the object
|
|
476 |
|
|
477 |
(It must explicitly coordinate with its supertype to save its state.)
|
|
478 |
|
|
479 |
- Implement a `readExternal` method to read the data written by the
|
|
480 |
`writeExternal` method from the stream and restore the state of the object
|
|
481 |
|
|
482 |
(It must explicitly coordinate with the supertype to save its state.)
|
|
483 |
|
|
484 |
- Have the `writeExternal` and `readExternal` methods be solely responsible
|
|
485 |
for the format, if an externally defined format is written
|
|
486 |
|
|
487 |
**Note:** The `writeExternal` and `readExternal` methods are public and
|
|
488 |
raise the risk that a client may be able to write or read information in
|
|
489 |
the object other than by using its methods and fields. These methods must
|
|
490 |
be used only when the information held by the object is not sensitive or
|
|
491 |
when exposing it does not present a security risk.
|
|
492 |
|
|
493 |
- Have a public no-arg constructor
|
|
494 |
|
|
495 |
**Note:** Inner classes associated with enclosing instances cannot have
|
|
496 |
no-arg constructors, since constructors of such classes implicitly accept
|
|
497 |
the enclosing instance as a prepended parameter. Consequently the
|
|
498 |
`Externalizable` interface mechanism cannot be used for inner classes and
|
|
499 |
they should implement the `Serializable` interface, if they must be
|
|
500 |
serialized. Several limitations exist for serializable inner classes as
|
|
501 |
well, however; see [Section 1.10, "The Serializable
|
|
502 |
Interface"](#the-serializable-interface), for a full enumeration.
|
|
503 |
|
|
504 |
An Externalizable class can optionally define the following methods:
|
|
505 |
|
|
506 |
- A `writeReplace` method to allow a class to nominate a replacement object
|
|
507 |
to be written to the stream
|
|
508 |
|
|
509 |
(See [Section 2.5, "The writeReplace
|
|
510 |
Method"](output.html#the-writereplace-method) for additional information.)
|
|
511 |
|
|
512 |
- A `readResolve` method to allow a class to designate a replacement object
|
|
513 |
for the object just read from the stream
|
|
514 |
|
|
515 |
(See [Section 3.7, "The readResolve
|
|
516 |
Method"](input.html#the-readresolve-method) for additional information.)
|
|
517 |
|
|
518 |
## 1.12 Serialization of Enum Constants
|
|
519 |
|
|
520 |
Enum constants are serialized differently than ordinary serializable or
|
|
521 |
externalizable objects. The serialized form of an enum constant consists solely
|
|
522 |
of its name; field values of the constant are not present in the form. To
|
|
523 |
serialize an enum constant, `ObjectOutputStream` writes the value returned by
|
|
524 |
the enum constant's `name` method. To deserialize an enum constant,
|
|
525 |
`ObjectInputStream` reads the constant name from the stream; the deserialized
|
|
526 |
constant is then obtained by calling the `java.lang.Enum.valueOf` method,
|
|
527 |
passing the constant's enum type along with the received constant name as
|
|
528 |
arguments. Like other serializable or externalizable objects, enum constants
|
|
529 |
can function as the targets of back references appearing subsequently in the
|
|
530 |
serialization stream.
|
|
531 |
|
|
532 |
The process by which enum constants are serialized cannot be customized: any
|
|
533 |
class-specific `writeObject`, `readObject`, `readObjectNoData`, `writeReplace`,
|
|
534 |
and `readResolve` methods defined by enum types are ignored during
|
|
535 |
serialization and deserialization. Similarly, any `serialPersistentFields` or
|
|
536 |
`serialVersionUID` field declarations are also ignored--all enum types have a
|
|
537 |
fixed `serialVersionUID` of `0L`. Documenting serializable fields and data for
|
|
538 |
enum types is unnecessary, since there is no variation in the type of data
|
|
539 |
sent.
|
|
540 |
|
|
541 |
## 1.13 Protecting Sensitive Information
|
|
542 |
|
|
543 |
When developing a class that provides controlled access to resources, care must
|
|
544 |
be taken to protect sensitive information and functions. During
|
|
545 |
deserialization, the private state of the object is restored. For example, a
|
|
546 |
file descriptor contains a handle that provides access to an operating system
|
|
547 |
resource. Being able to forge a file descriptor would allow some forms of
|
|
548 |
illegal access, since restoring state is done from a stream. Therefore, the
|
|
549 |
serializing runtime must take the conservative approach and not trust the
|
|
550 |
stream to contain only valid representations of objects. To avoid compromising
|
|
551 |
a class, the sensitive state of an object must not be restored from the stream,
|
|
552 |
or it must be reverified by the class. Several techniques are available to
|
|
553 |
protect sensitive data in classes.
|
|
554 |
|
|
555 |
The easiest technique is to mark fields that contain sensitive data as *private
|
|
556 |
transient*. Transient fields are not persistent and will not be saved by any
|
|
557 |
persistence mechanism. Marking the field will prevent the state from appearing
|
|
558 |
in the stream and from being restored during deserialization. Since writing and
|
|
559 |
reading (of private fields) cannot be superseded outside of the class, the
|
|
560 |
transient fields of the class are safe.
|
|
561 |
|
|
562 |
Particularly sensitive classes should not be serialized at all. To accomplish
|
|
563 |
this, the object should not implement either the `Serializable` or the
|
|
564 |
`Externalizable` interface.
|
|
565 |
|
|
566 |
Some classes may find it beneficial to allow writing and reading but
|
|
567 |
specifically handle and revalidate the state as it is deserialized. The class
|
|
568 |
should implement `writeObject` and `readObject` methods to save and restore
|
|
569 |
only the appropriate state. If access should be denied, throwing a
|
|
570 |
`NotSerializableException` will prevent further access.
|
|
571 |
|
|
572 |
-------------------------------------------------------------------------------
|
|
573 |
|
|
574 |
*[Copyright](../../../legal/SMICopyright.html) © 2005, 2017, Oracle
|
|
575 |
and/or its affiliates. All rights reserved.*
|