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](input.html) | [NEXT](version.html)'
|
|
24 |
include-after: '[CONTENTS](index.html) | [PREV](input.html) | [NEXT](version.html)'
|
|
25 |
|
|
26 |
title: 'Java Object Serialization Specification: 4 - Class Descriptors'
|
|
27 |
---
|
|
28 |
|
|
29 |
- [The ObjectStreamClass Class](#the-objectstreamclass-class)
|
|
30 |
- [Dynamic Proxy Class Descriptors](#dynamic-proxy-class-descriptors)
|
|
31 |
- [Serialized Form](#serialized-form)
|
|
32 |
- [The ObjectStreamField Class](#the-objectstreamfield-class)
|
|
33 |
- [Inspecting Serializable Classes](#inspecting-serializable-classes)
|
|
34 |
- [Stream Unique Identifiers](#stream-unique-identifiers)
|
|
35 |
|
|
36 |
-------------------------------------------------------------------------------
|
|
37 |
|
|
38 |
## 4.1 The ObjectStreamClass Class
|
|
39 |
|
|
40 |
The `ObjectStreamClass` provides information about classes that are saved in a
|
|
41 |
Serialization stream. The descriptor provides the fully-qualified name of the
|
|
42 |
class and its serialization version UID. A `SerialVersionUID` identifies the
|
|
43 |
unique original class version for which this class is capable of writing
|
|
44 |
streams and from which it can read.
|
|
45 |
|
|
46 |
```
|
|
47 |
package java.io;
|
|
48 |
|
|
49 |
public class ObjectStreamClass
|
|
50 |
{
|
|
51 |
public static ObjectStreamClass lookup(Class cl);
|
|
52 |
|
|
53 |
public static ObjectStreamClass lookupAny(Class cl);
|
|
54 |
|
|
55 |
public String getName();
|
|
56 |
|
|
57 |
public Class forClass();
|
|
58 |
|
|
59 |
public ObjectStreamField[] getFields();
|
|
60 |
|
|
61 |
public long getSerialVersionUID();
|
|
62 |
|
|
63 |
public String toString();
|
|
64 |
}
|
|
65 |
```
|
|
66 |
|
|
67 |
The `lookup` method returns the `ObjectStreamClass` descriptor for the
|
|
68 |
specified class in the virtual machine. If the class has defined
|
|
69 |
`serialVersionUID` it is retrieved from the class. If the `serialVersionUID` is
|
|
70 |
not defined by the class, it is computed from the definition of the class in
|
|
71 |
the virtual machine. *I*f the specified class is not serializable or
|
|
72 |
externalizable, *null* is returned.
|
|
73 |
|
|
74 |
The `lookupAny` method behaves like the `lookup` method, except that it returns
|
|
75 |
the descriptor for any class, regardless of whether it implements
|
|
76 |
`Serializable`. The `serialVersionUID` of a class that does not implement
|
|
77 |
`Serializable` is *0L.*
|
|
78 |
|
|
79 |
The `getName` method returns the name of the class, in the same format that is
|
|
80 |
used by the `Class.getName` method.
|
|
81 |
|
|
82 |
The `forClass` method returns the `Class` in the local virtual machine if one
|
|
83 |
was found by `ObjectInputStream.resolveClass` method. Otherwise, it returns
|
|
84 |
*null*.
|
|
85 |
|
|
86 |
The `getFields` method returns an array of `ObjectStreamField` objects that
|
|
87 |
represent the serializable fields of this class.
|
|
88 |
|
|
89 |
The `getSerialVersionUID` method returns the `serialVersionUID` of this class.
|
|
90 |
Refer to [Section 4.6, "Stream Unique
|
|
91 |
Identifiers"](#stream-unique-identifiers). If not specified by the class, the
|
|
92 |
value returned is a hash computed from the class's name, interfaces, methods,
|
|
93 |
and fields using the Secure Hash Algorithm (SHA) as defined by the National
|
|
94 |
Institute of Standards.
|
|
95 |
|
|
96 |
The `toString` method returns a printable representation of the class
|
|
97 |
descriptor including the name of the class and the `serialVersionUID`.
|
|
98 |
|
|
99 |
## 4.2 Dynamic Proxy Class Descriptors
|
|
100 |
|
|
101 |
ObjectStreamClass descriptors are also used to provide information about
|
|
102 |
dynamic proxy classes (e.g., classes obtained via calls to the getProxyClass
|
|
103 |
method of java.lang.reflect.Proxy) saved in a serialization stream. A dynamic
|
|
104 |
proxy class itself has no serializable fields and a serialVersionUID of 0L. In
|
|
105 |
other words, when the Class object for a dynamic proxy class is passed to the
|
|
106 |
static lookup method of ObjectStreamClass, the returned ObjectStreamClass
|
|
107 |
instance will have the following properties:
|
|
108 |
|
|
109 |
- Invoking its getSerialVersionUID method will return 0L.
|
|
110 |
- Invoking its getFields method will return an array of length zero.
|
|
111 |
- Invoking its getField method with any String argument will return null.
|
|
112 |
|
|
113 |
## 4.3 Serialized Form
|
|
114 |
|
|
115 |
The serialized form of an ObjectStreamClass instance depends on whether or not
|
|
116 |
the Class object it represents is serializable, externalizable, or a dynamic
|
|
117 |
proxy class.
|
|
118 |
|
|
119 |
When an `ObjectStreamClass` instance that does not represent a dynamic proxy
|
|
120 |
class is written to the stream, it writes the class name and
|
|
121 |
`serialVersionUID`, flags, and the number of fields. Depending on the class,
|
|
122 |
additional information may be written:
|
|
123 |
|
|
124 |
- For non-serializable classes, the number of fields is always zero. Neither
|
|
125 |
the `SC_SERIALIZABLE` nor the `SC_EXTERNALIZABLE` flag bits are set.
|
|
126 |
|
|
127 |
- For serializable classes, the `SC_SERIALIZABLE` flag is set, the number of
|
|
128 |
fields counts the number of serializable fields and is followed by a
|
|
129 |
descriptor for each serializable field. The descriptors are written in
|
|
130 |
canonical order. The descriptors for primitive typed fields are written
|
|
131 |
first sorted by field name followed by descriptors for the object typed
|
|
132 |
fields sorted by field name. The names are sorted using `String.compareTo`.
|
|
133 |
For details of the format, refer to [Section 6.4, "Grammar for the Stream
|
|
134 |
Format"](protocol.html#grammar-for-the-stream-format).
|
|
135 |
|
|
136 |
- For externalizable classes, flags includes the `SC_EXTERNALIZABLE` flag,
|
|
137 |
and the number of fields is always zero.
|
|
138 |
|
|
139 |
- For enum types, flags includes the `SC_ENUM` flag, and the number of fields
|
|
140 |
is always zero.
|
|
141 |
|
|
142 |
When an ObjectOutputStream serializes the ObjectStreamClass descriptor for a
|
|
143 |
dynamic proxy class, as determined by passing its Class object to the
|
|
144 |
isProxyClass method of java.lang.reflect.Proxy, it writes the number of
|
|
145 |
interfaces that the dynamic proxy class implements, followed by the interface
|
|
146 |
names. Interfaces are listed in the order that they are returned by invoking
|
|
147 |
the getInterfaces method on the Class object of the dynamic proxy class.
|
|
148 |
|
|
149 |
The serialized representations of ObjectStreamClass descriptors for dynamic
|
|
150 |
proxy classes and non-dynamic proxy classes are differentiated through the use
|
|
151 |
of different typecodes (`TC_PROXYCLASSDESC` and `TC_CLASSDESC`, respectively);
|
|
152 |
for a more detailed specification of the grammar, see [Section 6.4, "Grammar
|
|
153 |
for the Stream Format"](protocol.html#grammar-for-the-stream-format).
|
|
154 |
|
|
155 |
## 4.4 The ObjectStreamField Class
|
|
156 |
|
|
157 |
An `ObjectStreamField` represents a serializable field of a serializable class.
|
|
158 |
The serializable fields of a class can be retrieved from the
|
|
159 |
`ObjectStreamClass`.
|
|
160 |
|
|
161 |
The special static serializable field, `serialPersistentFields`, is an array of
|
|
162 |
`ObjectStreamField` components that is used to override the default
|
|
163 |
serializable fields.
|
|
164 |
|
|
165 |
```
|
|
166 |
package java.io;
|
|
167 |
|
|
168 |
public class ObjectStreamField implements Comparable {
|
|
169 |
|
|
170 |
public ObjectStreamField(String fieldName,
|
|
171 |
Class fieldType);
|
|
172 |
|
|
173 |
public ObjectStreamField(String fieldName,
|
|
174 |
Class fieldType,
|
|
175 |
boolean unshared);
|
|
176 |
|
|
177 |
public String getName();
|
|
178 |
|
|
179 |
public Class getType();
|
|
180 |
|
|
181 |
public String getTypeString();
|
|
182 |
|
|
183 |
public char getTypeCode();
|
|
184 |
|
|
185 |
public boolean isPrimitive();
|
|
186 |
|
|
187 |
public boolean isUnshared();
|
|
188 |
|
|
189 |
public int getOffset();
|
|
190 |
|
|
191 |
protected void setOffset(int offset);
|
|
192 |
|
|
193 |
public int compareTo(Object obj);
|
|
194 |
|
|
195 |
public String toString();
|
|
196 |
}
|
|
197 |
```
|
|
198 |
|
|
199 |
`ObjectStreamField` objects are used to specify the serializable fields of a
|
|
200 |
class or to describe the fields present in a stream. Its constructors accept
|
|
201 |
arguments describing the field to represent: a string specifying the name of
|
|
202 |
the field, a `Class` object specifying the type of the field, and a `boolean`
|
|
203 |
flag (implicitly `false` for the two-argument constructor) indicating whether
|
|
204 |
or not values of the represented field should be read and written as "unshared"
|
|
205 |
objects if default serialization/deserialization is in use (see the
|
|
206 |
descriptions of the `ObjectInputStream.readUnshared` and
|
|
207 |
`ObjectOutputStream.writeUnshared` methods in [Section 3.1, "The
|
|
208 |
ObjectInputStream Class"](input.html#the-objectinputstream-class) and [Section
|
|
209 |
2.1, "The ObjectOutputStream Class"](output.html#the-objectoutputstream-class),
|
|
210 |
respectively).
|
|
211 |
|
|
212 |
The `getName` method returns the name of the serializable field.
|
|
213 |
|
|
214 |
The `getType` method returns the type of the field.
|
|
215 |
|
|
216 |
The `getTypeString` method returns the type signature of the field.
|
|
217 |
|
|
218 |
The `getTypeCode` method returns a character encoding of the field type ('`B`'
|
|
219 |
for `byte`, '`C`' for `char`, '`D`' for `double`, '`F`' for `float`, '`I`' for
|
|
220 |
`int`, '`J`' for `long`, '`L`' for non-array object types, '`S`' for `short`,
|
|
221 |
'`Z`' for `boolean`, and '`[`' for arrays).
|
|
222 |
|
|
223 |
The `isPrimitive` method returns `true` if the field is of primitive type, or
|
|
224 |
`false` otherwise.
|
|
225 |
|
|
226 |
The `isUnshared` method returns `true` if values of the field should be written
|
|
227 |
as "unshared" objects, or `false` otherwise.
|
|
228 |
|
|
229 |
The `getOffset` method returns the offset of the field's value within instance
|
|
230 |
data of the class defining the field.
|
|
231 |
|
|
232 |
The `setOffset` method allows `ObjectStreamField` subclasses to modify the
|
|
233 |
offset value returned by the `getOffset` method.
|
|
234 |
|
|
235 |
The `compareTo` method compares `ObjectStreamFields` for use in sorting.
|
|
236 |
Primitive fields are ranked as "smaller" than non-primitive fields; fields
|
|
237 |
otherwise equal are ranked alphabetically.
|
|
238 |
|
|
239 |
The `toString` method returns a printable representation with name and type.
|
|
240 |
|
|
241 |
## 4.5 Inspecting Serializable Classes
|
|
242 |
|
|
243 |
The program *serialver* can be used to find out if a class is serializable and
|
|
244 |
to get its `serialVersionUID`. When invoked with the-show option, it puts up a
|
|
245 |
simple user interface. To find out if a class is serializable and to find out
|
|
246 |
its *serialVersionUID*`,` enter its full class name, then press either the
|
|
247 |
Enter or the Show button. The string printed can be copied and pasted into the
|
|
248 |
evolved class.
|
|
249 |
|
|
250 |
> ![*serialver, Serial Version Inspector program*](images/class.gif)
|
|
251 |
|
|
252 |
When invoked on the command line with one or more class names, serialver prints
|
|
253 |
the `serialVersionUID` for each class in a form suitable for copying into an
|
|
254 |
evolving class. When invoked with no arguments, it prints a usage line.
|
|
255 |
|
|
256 |
## 4.6 Stream Unique Identifiers
|
|
257 |
|
|
258 |
Each versioned class must identify the original class version for which it is
|
|
259 |
capable of writing streams and from which it can read. For example, a versioned
|
|
260 |
class must declare:
|
|
261 |
|
|
262 |
```
|
|
263 |
private static final long serialVersionUID = 3487495895819393L;
|
|
264 |
```
|
|
265 |
|
|
266 |
The stream-unique identifier is a 64-bit hash of the class name, interface
|
|
267 |
class names, methods, and fields. The value must be declared in all versions of
|
|
268 |
a class except the first. It may be declared in the original class but is not
|
|
269 |
required. The value is fixed for all compatible classes. If the SUID is not
|
|
270 |
declared for a class, the value defaults to the hash for that class. The
|
|
271 |
`serialVersionUID` for dynamic proxy classes and enum types always have the
|
|
272 |
value *0L*. Array classes cannot declare an explicit `serialVersionUID`, so
|
|
273 |
they always have the default computed value, but the requirement for matching
|
|
274 |
`serialVersionUID` values is waived for array classes.
|
|
275 |
|
|
276 |
**Note:** It is strongly recommended that all serializable classes explicitly
|
|
277 |
declare `serialVersionUID` values, since the default `serialVersionUID`
|
|
278 |
computation is highly sensitive to class details that may vary depending on
|
|
279 |
compiler implementations, and can thus result in unexpected `serialVersionUID`
|
|
280 |
conflicts during deserialization, causing deserialization to fail.
|
|
281 |
|
|
282 |
The initial version of an `Externalizable` class must output a stream data
|
|
283 |
format that is extensible in the future. The initial version of the method
|
|
284 |
`readExternal` has to be able to read the output format of all future versions
|
|
285 |
of the method `writeExternal`.
|
|
286 |
|
|
287 |
The `serialVersionUID` is computed using the signature of a stream of bytes
|
|
288 |
that reflect the class definition. The National Institute of Standards and
|
|
289 |
Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a signature
|
|
290 |
for the stream. The first two 32-bit quantities are used to form a 64-bit hash.
|
|
291 |
A `java.lang.DataOutputStream` is used to convert primitive data types to a
|
|
292 |
sequence of bytes. The values input to the stream are defined by the Java
|
|
293 |
Virtual Machine (VM) specification for classes. Class modifiers may include the
|
|
294 |
`ACC_PUBLIC`, `ACC_FINAL`, `ACC_INTERFACE`, and `ACC_ABSTRACT` flags; other
|
|
295 |
flags are ignored and do not affect `serialVersionUID` computation. Similarly,
|
|
296 |
for field modifiers, only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`,
|
|
297 |
`ACC_STATIC`, `ACC_FINAL`, `ACC_VOLATILE`, and `ACC_TRANSIENT` flags are used
|
|
298 |
when computing `serialVersionUID` values. For constructor and method modifiers,
|
|
299 |
only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`, `ACC_STATIC`,
|
|
300 |
`ACC_FINAL`, `ACC_SYNCHRONIZED`, `ACC_NATIVE`, `ACC_ABSTRACT` and `ACC_STRICT`
|
|
301 |
flags are used. Names and descriptors are written in the format used by the
|
|
302 |
`java.io.DataOutputStream.writeUTF` method.
|
|
303 |
|
|
304 |
The sequence of items in the stream is as follows:
|
|
305 |
|
|
306 |
1. The class name.
|
|
307 |
|
|
308 |
2. The class modifiers written as a 32-bit integer.
|
|
309 |
|
|
310 |
3. The name of each interface sorted by name.
|
|
311 |
|
|
312 |
4. For each field of the class sorted by field name (except `private static`
|
|
313 |
and `private transient` fields:
|
|
314 |
|
|
315 |
a. The name of the field.
|
|
316 |
|
|
317 |
b. The modifiers of the field written as a 32-bit integer.
|
|
318 |
|
|
319 |
c. The descriptor of the field.
|
|
320 |
|
|
321 |
5. If a class initializer exists, write out the following:
|
|
322 |
|
|
323 |
a. The name of the method, `<clinit>`.
|
|
324 |
|
|
325 |
b. The modifier of the method, `java.lang.reflect.Modifier.STATIC`,
|
|
326 |
written as a 32-bit integer.
|
|
327 |
|
|
328 |
c. The descriptor of the method, `()V`.
|
|
329 |
|
|
330 |
6. For each non-`private` constructor sorted by method name and signature:
|
|
331 |
|
|
332 |
a. The name of the method, `<init>`.
|
|
333 |
|
|
334 |
b. The modifiers of the method written as a 32-bit integer.
|
|
335 |
|
|
336 |
c. The descriptor of the method.
|
|
337 |
|
|
338 |
7. For each non-`private` method sorted by method name and signature:
|
|
339 |
|
|
340 |
a. The name of the method.
|
|
341 |
|
|
342 |
b. The modifiers of the method written as a 32-bit integer.
|
|
343 |
|
|
344 |
c. The descriptor of the method.
|
|
345 |
|
|
346 |
8. The SHA-1 algorithm is executed on the stream of bytes produced by
|
|
347 |
`DataOutputStream` and produces five 32-bit values `sha[0..4]`.
|
|
348 |
|
|
349 |
9. The hash value is assembled from the first and second 32-bit values of the
|
|
350 |
SHA-1 message digest. If the result of the message digest, the five 32-bit
|
|
351 |
words `H0 H1 H2 H3 H4`, is in an array of five `int` values named `sha`,
|
|
352 |
the hash value would be computed as follows:
|
|
353 |
|
|
354 |
```
|
|
355 |
long hash = ((sha[0] >>> 24) & 0xFF) |
|
|
356 |
((sha[0] >>> 16) & 0xFF) << 8 |
|
|
357 |
((sha[0] >>> 8) & 0xFF) << 16 |
|
|
358 |
((sha[0] >>> 0) & 0xFF) << 24 |
|
|
359 |
((sha[1] >>> 24) & 0xFF) << 32 |
|
|
360 |
((sha[1] >>> 16) & 0xFF) << 40 |
|
|
361 |
((sha[1] >>> 8) & 0xFF) << 48 |
|
|
362 |
((sha[1] >>> 0) & 0xFF) << 56;
|
|
363 |
```
|
|
364 |
|
|
365 |
-------------------------------------------------------------------------------
|
|
366 |
|
|
367 |
*[Copyright](../../../legal/SMICopyright.html) © 2005, 2017, Oracle
|
|
368 |
and/or its affiliates. All rights reserved.*
|