forked from bjmashibing/java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.html
More file actions
253 lines (209 loc) · 36.8 KB
/
input.html
File metadata and controls
253 lines (209 loc) · 36.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Java Object Serialization Specification: 3 - Object Input Classes</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<link rel="stylesheet" href="../../resources/jdk-default.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<a href="index.html">CONTENTS</a> | <a href="output.html">PREV</a> | <a href="class.html">NEXT</a>
<header id="title-block-header">
<h1 class="title">Java Object Serialization Specification: 3 - Object Input Classes</h1>
</header>
<ul>
<li><a href="#the-objectinputstream-class">The ObjectInputStream Class</a></li>
<li><a href="#the-objectinputstream.getfield-class">The ObjectInputStream.GetField Class</a></li>
<li><a href="#the-objectinputvalidation-interface">The ObjectInputValidation Interface</a></li>
<li><a href="#the-readobject-method">The readObject Method</a></li>
<li><a href="#the-readexternal-method">The readExternal Method</a></li>
<li><a href="#the-readresolve-method">The readResolve Method</a></li>
</ul>
<hr />
<h2 id="the-objectinputstream-class">3.1 The ObjectInputStream Class</h2>
<p>Class <code>ObjectInputStream</code> implements object deserialization. It maintains the state of the stream including the set of objects already deserialized. Its methods allow primitive types and objects to be read from a stream written by <code>ObjectOutputStream</code>. It manages restoration of the object and the objects that it refers to from the stream.</p>
<pre><code>package java.io;
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
{
public ObjectInputStream(InputStream in)
throws StreamCorruptedException, IOException;
public final Object readObject()
throws OptionalDataException, ClassNotFoundException,
IOException;
public Object readUnshared()
throws OptionalDataException, ClassNotFoundException,
IOException;
public void defaultReadObject()
throws IOException, ClassNotFoundException,
NotActiveException;
public GetField readFields()
throws IOException;
public synchronized void registerValidation(
ObjectInputValidation obj, int prio)
throws NotActiveException, InvalidObjectException;
protected ObjectStreamClass readClassDescriptor()
throws IOException, ClassNotFoundException;
protected Class resolveClass(ObjectStreamClass v)
throws IOException, ClassNotFoundException;
protected Object resolveObject(Object obj)
throws IOException;
protected boolean enableResolveObject(boolean enable)
throws SecurityException;
protected void readStreamHeader()
throws IOException, StreamCorruptedException;
public int read() throws IOException;
public int read(byte[] data, int offset, int length)
throws IOException
public int available() throws IOException;
public void close() throws IOException;
public boolean readBoolean() throws IOException;
public byte readByte() throws IOException;
public int readUnsignedByte() throws IOException;
public short readShort() throws IOException;
public int readUnsignedShort() throws IOException;
public char readChar() throws IOException;
public int readInt() throws IOException;
public long readLong() throws IOException;
public float readFloat() throws IOException;
public double readDouble() throws IOException;
public void readFully(byte[] data) throws IOException;
public void readFully(byte[] data, int offset, int size)
throws IOException;
public int skipBytes(int len) throws IOException;
public String readLine() throws IOException;
public String readUTF() throws IOException;
// Class to provide access to serializable fields.
static abstract public class GetField
{
public ObjectStreamClass getObjectStreamClass();
public boolean defaulted(String name)
throws IOException, IllegalArgumentException;
public char get(String name, char default)
throws IOException, IllegalArgumentException;
public boolean get(String name, boolean default)
throws IOException, IllegalArgumentException;
public byte get(String name, byte default)
throws IOException, IllegalArgumentException;
public short get(String name, short default)
throws IOException, IllegalArgumentException;
public int get(String name, int default)
throws IOException, IllegalArgumentException;
public long get(String name, long default)
throws IOException, IllegalArgumentException;
public float get(String name, float default)
throws IOException, IllegalArgumentException;
public double get(String name, double default)
throws IOException, IllegalArgumentException;
public Object get(String name, Object default)
throws IOException, IllegalArgumentException;
}
protected ObjectInputStream()
throws StreamCorruptedException, IOException;
protected readObjectOverride()
throws OptionalDataException, ClassNotFoundException,
IOException;
}</code></pre>
<p>The single-argument <code>ObjectInputStream</code> constructor requires an <code>InputStream</code>. The constructor calls <code>readStreamHeader</code> to read and verifies the header and version written by the corresponding <code>ObjectOutputStream.writeStreamHeader</code> method. If a security manager is installed, this constructor checks for the <code>"enableSubclassImplementation"</code> <code>SerializablePermission</code> when invoked directly or indirectly by the constructor of a subclass which overrides the <code>readFields</code> and/or <code>readUnshared</code> methods.</p>
<p><strong>Note:</strong> The <code>ObjectInputStream</code> constructor blocks until it completes reading the serialization stream header. Code which waits for an <code>ObjectInputStream</code> to be constructed before creating the corresponding <code>ObjectOutputStream</code> for that stream will deadlock, since the <code>ObjectInputStream</code> constructor will block until a header is written to the stream, and the header will not be written to the stream until the <code>ObjectOutputStream</code> constructor executes. This problem can be resolved by creating the <code>ObjectOutputStream</code> before the <code>ObjectInputStream</code>, or otherwise removing the timing dependency between completion of <code>ObjectInputStream</code> construction and the creation of the <code>ObjectOutputStream</code>.</p>
<p>The <code>readObject</code> method is used to deserialize an object from the stream. It reads from the stream to reconstruct an object.</p>
<ol type="1">
<li><p>If the <code>ObjectInputStream</code> subclass is overriding the implementation, call the <code>readObjectOverride</code> method and return. Reimplementation is described at the end of this section.</p></li>
<li><p>If a block data record occurs in the stream, throw a <code>BlockDataException</code> with the number of available bytes.</p></li>
<li><p>If the object in the stream is null, return null.</p></li>
<li><p>If the object in the stream is a handle to a previous object, return the object.</p></li>
<li><p>If the object in the stream is a <code>Class</code>, read its <code>ObjectStreamClass</code> descriptor, add it and its handle to the set of known objects, and return the corresponding <code>Class</code> object.</p></li>
<li><p>If the object in the stream is an <code>ObjectStreamClass</code>, read in its data according to the formats described in <a href="class.html#serialized-form">Section 4.3, "Serialized Form"</a>. Add it and its handle to the set of known objects. In versions 1.3 and later of the Java 2 SDK, Standard Edition, the <code>readClassDescriptor</code> method is called to read in the <code>ObjectStreamClass</code> if it represents a class that is not a dynamic proxy class, as indicated in the stream data. If the class descriptor represents a dynamic proxy class, call the <code>resolveProxyClass</code> method on the stream to get the local class for the descriptor; otherwise, call the <code>resolveClass</code> method on the stream to get the local class. If the class cannot be resolved, throw a ClassNotFoundException. Return the resulting <code>ObjectStreamClass</code> object.</p></li>
<li><p>If the object in the stream is a <code>String</code>, read its length information followed by the contents of the string encoded in modified UTF-8. For details, refer to <a href="protocol.html#stream-elements">Section 6.2, "Stream Elements"</a>. Add the <code>String</code> and its handle to the set of known objects, and proceed to Step 12.</p></li>
<li><p>If the object in the stream is an array, read its <code>ObjectStreamClass</code> and the length of the array. Allocate the array, and add it and its handle in the set of known objects. Read each element using the appropriate method for its type and assign it to the array. Proceed to Step 12.</p></li>
<li><p>If the object in the stream is an enum constant, read its <code>ObjectStreamClass</code> and the enum constant name. If the <code>ObjectStreamClass</code> represents a class that is not an enum type, an <code>InvalidClassException</code> is thrown. Obtain a reference to the enum constant by calling the <code>java.lang.Enum.valueOf</code> method, passing the enum type bound to the received <code>ObjectStreamClass</code> along with the received name as arguments. If the <code>valueOf</code> method throws an <code>IllegalArgumentException</code>, an <code>InvalidObjectException</code> is thrown with the <code>IllegalArgumentException</code> as its cause. Add the enum constant and its handle in the set of known objects, and proceed to Step 12.</p></li>
<li><p>For all other objects, the <code>ObjectStreamClass</code> of the object is read from the stream. The local class for that <code>ObjectStreamClass</code> is retrieved. The class must be serializable or externalizable, and must not be an enum type. If the class does not satisfy these criteria, an <code>InvalidClassException</code> is thrown.</p></li>
<li><p>An instance of the class is allocated. The instance and its handle are added to the set of known objects. The contents restored appropriately:</p>
<ol type="a">
<li><p>For serializable objects, the no-arg constructor for the first non-serializable supertype is run. For serializable classes, the fields are initialized to the default value appropriate for its type. Then the fields of each class are restored by calling class-specific <code>readObject</code> methods, or if these are not defined, by calling the <code>defaultReadObject</code> method. Note that field initializers and constructors are not executed for serializable classes during deserialization. In the normal case, the version of the class that wrote the stream will be the same as the class reading the stream. In this case, all of the supertypes of the object in the stream will match the supertypes in the currently-loaded class. If the version of the class that wrote the stream had different supertypes than the loaded class, the <code>ObjectInputStream</code> must be more careful about restoring or initializing the state of the differing classes. It must step through the classes, matching the available data in the stream with the classes of the object being restored. Data for classes that occur in the stream, but do not occur in the object, is discarded. For classes that occur in the object, but not in the stream, the class fields are set to default values by default serialization.</p></li>
<li><p>For externalizable objects, the no-arg constructor for the class is run and then the <code>readExternal</code> method is called to restore the contents of the object.</p></li>
</ol></li>
<li><p>Process potential substitutions by the class of the object and/or by a subclass of <code>ObjectInputStream</code>:</p>
<ol type="a">
<li><p>If the class of the object is not an enum type and defines the appropriate <code>readResolve</code> method, the method is called to allow the object to replace itself.</p></li>
<li><p>Then if previously enabled by <code>enableResolveObject,</code> the <code>resolveObject</code> method is called to allow subclasses of the stream to examine and replace the object. If the previous step did replace the original object, the <code>resolveObject</code> method is called with the replacement object. If a replacement took place, the table of known objects is updated so the replacement object is associated with the handle. The replacement object is then returned from <code>readObject</code>.</p></li>
</ol></li>
</ol>
<p>All of the methods for reading primitives types only consume bytes from the block data records in the stream. If a read for primitive data occurs when the next item in the stream is an object, the read methods return <em>-1</em> or the <code>EOFException</code> as appropriate. The value of a primitive type is read by a <code>DataInputStream</code> from the block data record.</p>
<p>The exceptions thrown reflect errors during the traversal or exceptions that occur on the underlying stream. If any exception is thrown, the underlying stream is left in an unknown and unusable state.</p>
<p>When the reset token occurs in the stream, all of the state of the stream is discarded. The set of known objects is cleared.</p>
<p>When the exception token occurs in the stream, the exception is read and a new <code>WriteAbortedException</code> is thrown with the terminating exception as an argument. The stream context is reset as described earlier.</p>
<p>The <code>readUnshared</code> method is used to read "unshared" objects from the stream. This method is identical to <code>readObject</code>, except that it prevents subsequent calls to <code>readObject</code> and <code>readUnshared</code> from returning additional references to the deserialized instance returned by the original call to <code>readUnshared</code>. Specifically:</p>
<ul>
<li><p>If <code>readUnshared</code> is called to deserialize a back-reference (the stream representation of an object which has been written previously to the stream), an <code>ObjectStreamException</code> will be thrown.</p></li>
<li><p>If <code>readUnshared</code> returns successfully, then any subsequent attempts to deserialize back-references to the stream handle deserialized by <code>readUnshared</code> will cause an <code>ObjectStreamException</code> to be thrown.</p></li>
</ul>
<p>Deserializing an object via <code>readUnshared</code> invalidates the stream handle associated with the returned object. Note that this in itself does not always guarantee that the reference returned by <code>readUnshared</code> is unique; the deserialized object may define a <code>readResolve</code> method which returns an object visible to other parties, or <code>readUnshared</code> may return a <code>Class</code> object or enum constant obtainable elsewhere in the stream or through external means. If the deserialized object defines a <code>readResolve</code> method and the invocation of that method returns an array, then <code>readUnshared</code> returns a shallow clone of that array; this guarantees that the returned array object is unique and cannot be obtained a second time from an invocation of <code>readObject</code> or <code>readUnshared</code> on the <code>ObjectInputStream</code>, even if the underlying data stream has been manipulated.</p>
<p>The <code>defaultReadObject</code> method is used to read the fields and object from the stream. It uses the class descriptor in the stream to read the fields in the canonical order by name and type from the stream. The values are assigned to the matching fields by name in the current class. Details of the versioning mechanism can be found in <a href="version.html#compatible-java-type-evolution">Section 5.5, "Compatible Java Type Evolution"</a>. Any field of the object that does not appear in the stream is set to its default value. Values that appear in the stream, but not in the object, are discarded. This occurs primarily when a later version of a class has written additional fields that do not occur in the earlier version. This method may only be called from the <code>readObject</code> method while restoring the fields of a class. When called at any other time, the <code>NotActiveException</code> is thrown.</p>
<p>The <code>readFields</code> method reads the values of the serializable fields from the stream and makes them available via the <code>GetField</code> class. The <code>readFields</code> method is only callable from within the <code>readObject</code> method of a serializable class. It cannot be called more than once or if <code>defaultReadObject</code> has been called. The <code>GetFields</code> object uses the current object's <code>ObjectStreamClass</code> to verify the fields that can be retrieved for this class. The <code>GetFields</code> object returned by <code>readFields</code> is only valid during this call to the classes <code>readObject</code> method. The fields may be retrieved in any order. Additional data may only be read directly from stream after <code>readFields</code> has been called.</p>
<p>The <code>registerValidation</code> method can be called to request a callback when the entire graph has been restored but before the object is returned to the original caller of <code>readObject</code>. The order of validate callbacks can be controlled using the priority. Callbacks registered with higher values are called before those with lower values. The object to be validated must support the <code>ObjectInputValidation</code> interface and implement the <code>validateObject</code> method. It is only correct to register validations during a call to a class's <code>readObject</code> method. Otherwise, a <code>NotActiveException</code> is thrown. If the callback object supplied to <code>registerValidation</code> is null, an <code>InvalidObjectException</code> is thrown.</p>
<p>Starting with the Java SDK, Standard Edition, v1.3, the <code>readClassDescriptor</code> method is used to read in all <code>ObjectStreamClass</code> objects. <code>readClassDescriptor</code> is called when the <code>ObjectInputStream</code> expects a class descriptor as the next item in the serialization stream. Subclasses of <code>ObjectInputStream</code> may override this method to read in class descriptors that have been written in non-standard formats (by subclasses of <code>ObjectOutputStream</code> which have overridden the <code>writeClassDescriptor</code> method). By default, this method reads class descriptors according to the format described in <a href="protocol.html#grammar-for-the-stream-format">Section 6.4, "Grammar for the Stream Format"</a>.</p>
<p>The <code>resolveClass</code> method is called while a class is being deserialized, and after the class descriptor has been read. Subclasses may extend this method to read other information about the class written by the corresponding subclass of <code>ObjectOutputStream</code>. The method must find and return the class with the given name and <code>serialVersionUID</code>. The default implementation locates the class by calling the class loader of the closest caller of <code>readObject</code> that has a class loader. If the class cannot be found <code>ClassNotFoundException</code> should be thrown. Prior to JDK 1.1.6, the <code>resolveClass</code> method was required to return the same fully qualified class name as the class name in the stream. In order to accommodate package renaming across releases, <code>method</code> <code>resolveClass</code> only needs to return a class with the same base class name and <code>SerialVersionUID</code> in JDK 1.1.6 and later versions.</p>
<p>The <code>resolveObject</code> method is used by trusted subclasses to monitor or substitute one object for another during deserialization. Resolving objects must be enabled explicitly by calling <code>enableResolveObject</code> before calling <code>readObject</code> for the first object to be resolved. Once enabled, <code>resolveObject</code> is called once for each serializable object just prior to the first time it is being returned from <code>readObject</code>. Note that the <code>resolveObject</code> method is not called for objects of the specially handled classes, <code>Class</code>, <code>ObjectStreamClass</code>, <code>String</code>, and arrays. A subclass's implementation of <code>resolveObject</code> may return a substitute object that will be assigned or returned instead of the original. The object returned must be of a type that is consistent and assignable to every reference of the original object or else a <code>ClassCastException</code> will be thrown. All assignments are type-checked. All references in the stream to the original object will be replaced by references to the substitute object.</p>
<p>The <code>enableResolveObject</code> method is called by trusted subclasses of <code>ObjectOutputStream</code> to enable the monitoring or substitution of one object for another during deserialization. Replacing objects is disabled until <code>enableResolveObject</code> is called with a <code>true</code> value. It may thereafter be disabled by setting it to <code>false</code>. The previous setting is returned. The <code>enableResolveObject</code> method checks if the stream has permission to request substitution during serialization. To ensure that the private state of objects is not unintentionally exposed, only trusted streams may use <code>resolveObject</code>. Trusted classes are those classes with a class loader equal to null or belong to a security protection domain that provides permission to enable substitution.</p>
<p>If the subclass of <code>ObjectInputStream</code> is not considered part of the system domain, a line has to be added to the security policy file to provide to a subclass of <code>ObjectInputStream</code> permission to call <code>enableResolveObject</code>. The <code>SerializablePermission</code> to add is <code>"enableSubstitution"</code>. <code>AccessControlException</code> is thrown if the protection domain of the subclass of <code>ObjectStreamClass</code> does not have permission to <code>"enableSubstitution"</code> by calling <code>enableResolveObject</code>. See the document Java Security Architecture (JDK 1.2) for additional information about the security model.</p>
<p>The <code>readStreamHeader</code> method reads and verifies the magic number and version of the stream. If they do not match, the <code>StreamCorruptedMismatch</code> is thrown.</p>
<p>To override the implementation of deserialization, a subclass of <code>ObjectInputStream</code> should call the protected no-arg <code>ObjectInputStream</code>, constructor. There is a security check within the no-arg constructor for <code>SerializablePermission "enableSubclassImplementation"</code> to ensure that only trusted classes are allowed to override the default implementation. This constructor does not allocate any private data for <code>ObjectInputStream</code> and sets a flag that indicates that the final <code>readObject</code> method should invoke the <code>readObjectOverride</code> method and return. All other <code>ObjectInputStream</code> methods are not final and can be directly overridden by the subclass.</p>
<h2 id="the-objectinputstream.getfield-class">3.2 The ObjectInputStream.GetField Class</h2>
<p>The class <code>ObjectInputStream.GetField</code> provides the API for getting the values of serializable fields. The protocol of the stream is the same as used by <code>defaultReadObject.</code> Using <code>readFields</code> to access the serializable fields does not change the format of the stream. It only provides an alternate API to access the values which does not require the class to have the corresponding non-transient and non-static fields for each named serializable field. The serializable fields are those declared using <code>serialPersistentFields</code> or if it is not declared the non-transient and non-static fields of the object. When the stream is read the available serializable fields are those written to the stream when the object was serialized. If the class that wrote the stream is a different version not all fields will correspond to the serializable fields of the current class. The available fields can be retrieved from the <code>ObjectStreamClass</code> of the <code>GetField</code> object.</p>
<p>The <code>getObjectStreamClass</code> method returns an <code>ObjectStreamClass</code> object representing the class in the stream. It contains the list of serializable fields.</p>
<p>The <code>defaulted</code> method returns <em>true</em> if the field is not present in the stream. An <code>IllegalArgumentException</code> is thrown if the requested field is not a serializable field of the current class.</p>
<p>Each <code>get</code> method returns the specified serializable field from the stream. I/O exceptions will be thrown if the underlying stream throws an exception. An <code>IllegalArgumentException</code> is thrown if the name or type does not match the name and type of an field serializable field of the current class. The default value is returned if the stream does not contain an explicit value for the field.</p>
<h2 id="the-objectinputvalidation-interface">3.3 The ObjectInputValidation Interface</h2>
<p>This interface allows an object to be called when a complete graph of objects has been deserialized. If the object cannot be made valid, it should throw the <code>ObjectInvalidException</code>. Any exception that occurs during a call to <code>validateObject</code> will terminate the validation process, and the <code>InvalidObjectException</code> will be thrown.</p>
<pre><code>package java.io;
public interface ObjectInputValidation
{
public void validateObject()
throws InvalidObjectException;
}</code></pre>
<h2 id="the-readobject-method">3.4 The readObject Method</h2>
<p>For serializable objects, the <code>readObject</code> method allows a class to control the deserialization of its own fields. Here is its signature:</p>
<pre><code>private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException;</code></pre>
<p>Each subclass of a serializable object may define its own <code>readObject</code> method. If a class does not implement the method, the default serialization provided by <code>defaultReadObject</code> will be used. When implemented, the class is only responsible for restoring its own fields, not those of its supertypes or subtypes.</p>
<p>The <code>readObject</code> method of the class, if implemented, is responsible for restoring the state of the class. The values of every field of the object whether transient or not, static or not are set to the default value for the fields type. Either <code>ObjectInputStream</code>'s <code>defaultReadObject</code> or <code>readFields</code> method must be called once (and only once) before reading any optional data written by the corresponding <code>writeObject</code> method; even if no optional data is read, <code>defaultReadObject</code> or <code>readFields</code> must still be invoked once. If the <code>readObject</code> method of the class attempts to read more data than is present in the optional part of the stream for this class, the stream will return <code>-1</code> for bytewise reads, throw an <code>EOFException</code> for primitive data reads (e.g., <code>readInt</code>, <code>readFloat</code>), or throw an <code>OptionalDataException</code> with the <code>eof</code> field set to <code>true</code> for object reads.</p>
<p>The responsibility for the format, structure, and versioning of the optional data lies completely with the class. The <code>@serialData</code> javadoc tag within the javadoc comment for the <code>readObject</code> method should be used to document the format and structure of the optional data.</p>
<p>If the class being restored is not present in the stream being read, then its <code>readObjectNoData</code> method, if defined, is invoked (instead of <code>readObject</code>); otherwise, its fields are initialized to the appropriate default values. For further detail, see <a href="#the-readobjectnodata-method">Section 3.5, "The readObjectNoData Method"</a>.</p>
<p>Reading an object from the <code>ObjectInputStream</code> is analogous to creating a new object. Just as a new object's constructors are invoked in the order from the superclass to the subclass, an object being read from a stream is deserialized from superclass to subclass. The <code>readObject</code> or <code>readObjectNoData</code> method is called instead of the constructor for each <code>Serializable</code> subclass during deserialization.</p>
<p>One last similarity between a constructor and a <code>readObject</code> method is that both provide the opportunity to invoke a method on an object that is not fully constructed. Any overridable (neither private, static nor final) method called while an object is being constructed can potentially be overridden by a subclass. Methods called during the construction phase of an object are resolved by the actual type of the object, not the type currently being initialized by either its constructor or <code>readObject</code>/<code>readObjectNoData</code> method. Therefore, calling an overridable method from within a <code>readObject</code> or <code>readObjectNoData</code> method may result in the unintentional invocation of a subclass method before the superclass has been fully initialized.</p>
<h2 id="the-readobjectnodata-method">3.5 The readObjectNoData Method</h2>
<p>For serializable objects, the <code>readObjectNoData</code> method allows a class to control the initialization of its own fields in the event that a subclass instance is deserialized and the serialization stream does not list the class in question as a superclass of the deserialized object. This may occur in cases where the receiving party uses a different version of the deserialized instance's class than the sending party, and the receiver's version extends classes that are not extended by the sender's version. This may also occur if the serialization stream has been tampered; hence, <code>readObjectNoData</code> is useful for initializing deserialized objects properly despite a "hostile" or incomplete source stream.</p>
<pre><code>private void readObjectNoData() throws ObjectStreamException;</code></pre>
<p>Each serializable class may define its own <code>readObjectNoData</code> method. If a serializable class does not define a <code>readObjectNoData</code> method, then in the circumstances listed above the fields of the class will be initialized to their default values (as listed in The Java Language Specification); this behavior is consistent with that of <code>ObjectInputStream</code> prior to version 1.4 of the Java 2 SDK, Standard Edition, when support for <code>readObjectNoData</code> methods was introduced. If a serializable class does define a <code>readObjectNoData</code> method and the aforementioned conditions arise, then <code>readObjectNoData</code> will be invoked at the point during deserialization when a class-defined <code>readObject</code> method would otherwise be called had the class in question been listed by the stream as a superclass of the instance being deserialized.</p>
<h2 id="the-readexternal-method">3.6 The readExternal Method</h2>
<p>Objects implementing <code>java.io.Externalizable</code> must implement the <code>readExternal</code> method to restore the entire state of the object. It must coordinate with its superclasses to restore their state. All of the methods of <code>ObjectInput</code> are available to restore the object's primitive typed fields and object fields.</p>
<pre><code>public void readExternal(ObjectInput stream)
throws IOException;</code></pre>
<p><strong>Note:</strong> The <code>readExternal</code> method is public, and it raises the risk of a client being able to overwrite an existing object from a stream. The class may add its own checks to insure that this is only called when appropriate.</p>
<p>A new stream protocol version has been introduced in JDK 1.2 to correct a problem with <code>Externalizable</code> objects. The old definition of <code>Externalizable</code> objects required the local virtual machine to find a <code>readExternal</code> method to be able to properly read an <code>Externalizable</code> object from the stream. The new format adds enough information to the stream protocol so serialization can skip an <code>Externalizable</code> object when the local <code>readExternal</code> method is not available. Due to class evolution rules, serialization must be able to skip an <code>Externalizable</code> object in the input stream if there is not a mapping for the object using the local classes.</p>
<p>An additional benefit of the new <code>Externalizable</code> stream format is that <code>ObjectInputStream</code> can detect attempts to read more External data than is available, and can also skip by any data that is left unconsumed by a <code>readExternal</code> method. The behavior of <code>ObjectInputStream</code> in response to a read past the end of External data is the same as the behavior when a class-defined <code>readObject</code> method attempts to read past the end of its optional data: bytewise reads will return <code>-1</code>, primitive reads will throw <code>EOFException</code>s, and object reads will throw <code>OptionalDataException</code>s with the <code>eof</code> field set to <code>true</code>.</p>
<p>Due to the format change, JDK 1.1.6 and earlier releases are not able to read the new format. <code>StreamCorruptedException</code> is thrown when JDK 1.1.6 or earlier attempts to read an <code>Externalizable</code> object from a stream written in <code>PROTOCOL_VERSION_2</code>. Compatibility issues are discussed in more detail in <a href="protocol.html#stream-protocol-versions">Section 6.3, "Stream Protocol Versions"</a>.</p>
<h2 id="the-readresolve-method">3.7 The readResolve Method</h2>
<p>For Serializable and Externalizable classes, the <code>readResolve</code> method allows a class to replace/resolve the object read from the stream before it is returned to the caller. By implementing the <code>readResolve</code> method, a class can directly control the types and instances of its own instances being deserialized. The method is defined as follows:</p>
<pre><code>ANY-ACCESS-MODIFIER Object readResolve()
throws ObjectStreamException;</code></pre>
<p>The <code>readResolve</code> method is called when <code>ObjectInputStream</code> has read an object from the stream and is preparing to return it to the caller. <code>ObjectInputStream</code> checks whether the class of the object defines the <code>readResolve</code> method. If the method is defined, the <code>readResolve</code> method is called to allow the object in the stream to designate the object to be returned. The object returned should be of a type that is compatible with all uses. If it is not compatible, a <code>ClassCastException</code> will be thrown when the type mismatch is discovered.</p>
<p>For example, a <code>Symbol</code> class could be created for which only a single instance of each symbol binding existed within a virtual machine. The <code>readResolve</code> method would be implemented to determine if that symbol was already defined and substitute the preexisting equivalent <code>Symbol</code> object to maintain the identity constraint. In this way the uniqueness of <code>Symbol</code> objects can be maintained across serialization.</p>
<p><strong>Note:</strong> The <code>readResolve</code> method is not invoked on the object until the object is fully constructed, so any references to this object in its object graph will not be updated to the new object nominated by <code>readResolve</code>. However, during the serialization of an object with the <code>writeReplace</code> method, all references to the original object in the replacement object's object graph are replaced with references to the replacement object. Therefore in cases where an object being serialized nominates a replacement object whose object graph has a reference to the original object, deserialization will result in an incorrect graph of objects. Furthermore, if the reference types of the object being read (nominated by <code>writeReplace</code>) and the original object are not compatible, the construction of the object graph will raise a <code>ClassCastException</code>.</p>
<hr />
<p><em><a href="../../legal/copyright.html">Copyright</a> © 2005, 2017, Oracle and/or its affiliates. All rights reserved.</em></p>
<a href="index.html">CONTENTS</a> | <a href="output.html">PREV</a> | <a href="class.html">NEXT</a>
</body>
</html>