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`. |
|
245 |
|
246 When invoked on the command line with one or more class names, serialver prints |
|
247 the `serialVersionUID` for each class in a form suitable for copying into an |
|
248 evolving class. When invoked with no arguments, it prints a usage line. |
|
249 |
|
250 ## 4.6 Stream Unique Identifiers |
|
251 |
|
252 Each versioned class must identify the original class version for which it is |
|
253 capable of writing streams and from which it can read. For example, a versioned |
|
254 class must declare: |
|
255 |
|
256 ``` |
|
257 private static final long serialVersionUID = 3487495895819393L; |
|
258 ``` |
|
259 |
|
260 The stream-unique identifier is a 64-bit hash of the class name, interface |
|
261 class names, methods, and fields. The value must be declared in all versions of |
|
262 a class except the first. It may be declared in the original class but is not |
|
263 required. The value is fixed for all compatible classes. If the SUID is not |
|
264 declared for a class, the value defaults to the hash for that class. The |
|
265 `serialVersionUID` for dynamic proxy classes and enum types always have the |
|
266 value *0L*. Array classes cannot declare an explicit `serialVersionUID`, so |
|
267 they always have the default computed value, but the requirement for matching |
|
268 `serialVersionUID` values is waived for array classes. |
|
269 |
|
270 **Note:** It is strongly recommended that all serializable classes explicitly |
|
271 declare `serialVersionUID` values, since the default `serialVersionUID` |
|
272 computation is highly sensitive to class details that may vary depending on |
|
273 compiler implementations, and can thus result in unexpected `serialVersionUID` |
|
274 conflicts during deserialization, causing deserialization to fail. |
|
275 |
|
276 The initial version of an `Externalizable` class must output a stream data |
|
277 format that is extensible in the future. The initial version of the method |
|
278 `readExternal` has to be able to read the output format of all future versions |
|
279 of the method `writeExternal`. |
|
280 |
|
281 The `serialVersionUID` is computed using the signature of a stream of bytes |
|
282 that reflect the class definition. The National Institute of Standards and |
|
283 Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a signature |
|
284 for the stream. The first two 32-bit quantities are used to form a 64-bit hash. |
|
285 A `java.lang.DataOutputStream` is used to convert primitive data types to a |
|
286 sequence of bytes. The values input to the stream are defined by the Java |
|
287 Virtual Machine (VM) specification for classes. Class modifiers may include the |
|
288 `ACC_PUBLIC`, `ACC_FINAL`, `ACC_INTERFACE`, and `ACC_ABSTRACT` flags; other |
|
289 flags are ignored and do not affect `serialVersionUID` computation. Similarly, |
|
290 for field modifiers, only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`, |
|
291 `ACC_STATIC`, `ACC_FINAL`, `ACC_VOLATILE`, and `ACC_TRANSIENT` flags are used |
|
292 when computing `serialVersionUID` values. For constructor and method modifiers, |
|
293 only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`, `ACC_STATIC`, |
|
294 `ACC_FINAL`, `ACC_SYNCHRONIZED`, `ACC_NATIVE`, `ACC_ABSTRACT` and `ACC_STRICT` |
|
295 flags are used. Names and descriptors are written in the format used by the |
|
296 `java.io.DataOutputStream.writeUTF` method. |
|
297 |
|
298 The sequence of items in the stream is as follows: |
|
299 |
|
300 1. The class name. |
|
301 |
|
302 2. The class modifiers written as a 32-bit integer. |
|
303 |
|
304 3. The name of each interface sorted by name. |
|
305 |
|
306 4. For each field of the class sorted by field name (except `private static` |
|
307 and `private transient` fields: |
|
308 |
|
309 a. The name of the field. |
|
310 |
|
311 b. The modifiers of the field written as a 32-bit integer. |
|
312 |
|
313 c. The descriptor of the field. |
|
314 |
|
315 5. If a class initializer exists, write out the following: |
|
316 |
|
317 a. The name of the method, `<clinit>`. |
|
318 |
|
319 b. The modifier of the method, `java.lang.reflect.Modifier.STATIC`, |
|
320 written as a 32-bit integer. |
|
321 |
|
322 c. The descriptor of the method, `()V`. |
|
323 |
|
324 6. For each non-`private` constructor sorted by method name and signature: |
|
325 |
|
326 a. The name of the method, `<init>`. |
|
327 |
|
328 b. The modifiers of the method written as a 32-bit integer. |
|
329 |
|
330 c. The descriptor of the method. |
|
331 |
|
332 7. For each non-`private` method sorted by method name and signature: |
|
333 |
|
334 a. The name of the method. |
|
335 |
|
336 b. The modifiers of the method written as a 32-bit integer. |
|
337 |
|
338 c. The descriptor of the method. |
|
339 |
|
340 8. The SHA-1 algorithm is executed on the stream of bytes produced by |
|
341 `DataOutputStream` and produces five 32-bit values `sha[0..4]`. |
|
342 |
|
343 9. The hash value is assembled from the first and second 32-bit values of the |
|
344 SHA-1 message digest. If the result of the message digest, the five 32-bit |
|
345 words `H0 H1 H2 H3 H4`, is in an array of five `int` values named `sha`, |
|
346 the hash value would be computed as follows: |
|
347 |
|
348 ``` |
|
349 long hash = ((sha[0] >>> 24) & 0xFF) | |
|
350 ((sha[0] >>> 16) & 0xFF) << 8 | |
|
351 ((sha[0] >>> 8) & 0xFF) << 16 | |
|
352 ((sha[0] >>> 0) & 0xFF) << 24 | |
|
353 ((sha[1] >>> 24) & 0xFF) << 32 | |
|
354 ((sha[1] >>> 16) & 0xFF) << 40 | |
|
355 ((sha[1] >>> 8) & 0xFF) << 48 | |
|
356 ((sha[1] >>> 0) & 0xFF) << 56; |
|
357 ``` |
|
358 |
|
359 ------------------------------------------------------------------------------- |
|
360 |
|
361 *[Copyright](../../../legal/SMICopyright.html) © 2005, 2017, Oracle |
|
362 and/or its affiliates. All rights reserved.* |
|