author | rriggs |
Tue, 16 May 2017 09:42:38 -0400 | |
changeset 45142 | be2c212f16dd |
parent 44787 | 0b323ea6d5ad |
permissions | -rw-r--r-- |
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 |
||
45142
be2c212f16dd
8180319: Update Serialization spec to omit obsolete serialver -show and change history
rriggs
parents:
44787
diff
changeset
|
23 |
include-before: '[CONTENTS](index.html) | [PREV](index.html) | [NEXT](output.html)' |
be2c212f16dd
8180319: Update Serialization spec to omit obsolete serialver -show and change history
rriggs
parents:
44787
diff
changeset
|
24 |
include-after: '[CONTENTS](index.html) | [PREV](index.html) | [NEXT](output.html)' |
44787 | 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.* |