19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27 package java.io;
28
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.Objects;
33 import java.util.StringJoiner;
34
35 import jdk.internal.util.ByteArray;
36 import jdk.internal.access.JavaLangAccess;
37 import jdk.internal.access.SharedSecrets;
38
39 import static jdk.internal.util.ModifiedUtf.putChar;
40 import static jdk.internal.util.ModifiedUtf.utfLen;
41
42 /**
43 * An ObjectOutputStream writes primitive data types and graphs of Java objects
44 * to an OutputStream. The objects can be read (reconstituted) using an
45 * ObjectInputStream. Persistent storage of objects can be accomplished by
46 * using a file for the stream. If the stream is a network socket stream, the
47 * objects can be reconstituted on another host or in another process.
48 *
49 * <p>Only objects that support the java.io.Serializable interface can be
50 * written to streams. The class of each serializable object is encoded
51 * including the class name and signature of the class, the values of the
52 * object's fields and arrays, and the closure of any other objects referenced
53 * from the initial objects.
54 *
55 * <p>The method writeObject is used to write an object to the stream. Any
56 * object, including Strings and arrays, is written with writeObject. Multiple
57 * objects or primitives can be written to the stream. The objects must be
58 * read back from the corresponding ObjectInputstream with the same types and
113 * implement the java.io.Serializable interface. Subclasses of Objects that
114 * are not serializable can be serializable. In this case the non-serializable
115 * class must have a no-arg constructor to allow its fields to be initialized.
116 * In this case it is the responsibility of the subclass to save and restore
117 * the state of the non-serializable class. It is frequently the case that the
118 * fields of that class are accessible (public, package, or protected) or that
119 * there are get and set methods that can be used to restore the state.
120 *
121 * <p>Serialization of an object can be prevented by implementing writeObject
122 * and readObject methods that throw the NotSerializableException. The
123 * exception will be caught by the ObjectOutputStream and abort the
124 * serialization process.
125 *
126 * <p>Implementing the Externalizable interface allows the object to assume
127 * complete control over the contents and format of the object's serialized
128 * form. The methods of the Externalizable interface, writeExternal and
129 * readExternal, are called to save and restore the objects state. When
130 * implemented by a class they can write and read their own state using all of
131 * the methods of ObjectOutput and ObjectInput. It is the responsibility of
132 * the objects to handle any versioning that occurs.
133 *
134 * <p>Enum constants are serialized differently than ordinary serializable or
135 * externalizable objects. The serialized form of an enum constant consists
136 * solely of its name; field values of the constant are not transmitted. To
137 * serialize an enum constant, ObjectOutputStream writes the string returned by
138 * the constant's name method. Like other serializable or externalizable
139 * objects, enum constants can function as the targets of back references
140 * appearing subsequently in the serialization stream. The process by which
141 * enum constants are serialized cannot be customized; any class-specific
142 * writeObject and writeReplace methods defined by enum types are ignored
143 * during serialization. Similarly, any serialPersistentFields or
144 * serialVersionUID field declarations are also ignored--all enum types have a
145 * fixed serialVersionUID of 0L.
146 *
147 * <p>Primitive data, excluding serializable fields and externalizable data, is
148 * written to the ObjectOutputStream in block-data records. A block data record
149 * is composed of a header and data. The block data header consists of a marker
150 * and the number of bytes to follow the header. Consecutive primitive data
151 * writes are merged into one block-data record. The blocking factor used for
152 * a block-data record will be 1024 bytes. Each block-data record will be
153 * filled up to 1024 bytes, or be written whenever there is a termination of
154 * block-data mode. Calls to the ObjectOutputStream methods writeObject,
155 * defaultWriteObject and writeFields initially terminate any existing
156 * block-data record.
157 *
158 * <p>Records are serialized differently than ordinary serializable or externalizable
159 * objects, see <a href="ObjectInputStream.html#record-serialization">record serialization</a>.
160 *
161 * @spec serialization/index.html Java Object Serialization Specification
162 * @author Mike Warres
163 * @author Roger Riggs
164 * @see java.io.DataOutput
165 * @see java.io.ObjectInputStream
166 * @see java.io.Serializable
167 * @see java.io.Externalizable
168 * @see <a href="{@docRoot}/../specs/serialization/output.html">
169 * <cite>Java Object Serialization Specification,</cite> Section 2, "Object Output Classes"</a>
170 * @since 1.1
171 */
172 public class ObjectOutputStream
173 extends OutputStream implements ObjectOutput, ObjectStreamConstants
174 {
175 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
176
177 /** filter stream for handling block data conversion */
178 private final BlockDataOutputStream bout;
179 /** obj -> wire handle map */
180 private final HandleTable handles;
287 case PROTOCOL_VERSION_1:
288 case PROTOCOL_VERSION_2:
289 protocol = version;
290 break;
291
292 default:
293 throw new IllegalArgumentException(
294 "unknown version: " + version);
295 }
296 }
297
298 /**
299 * Write the specified object to the ObjectOutputStream. The class of the
300 * object, the signature of the class, and the values of the non-transient
301 * and non-static fields of the class and all of its supertypes are
302 * written. Default serialization for a class can be overridden using the
303 * writeObject and the readObject methods. Objects referenced by this
304 * object are written transitively so that a complete equivalent graph of
305 * objects can be reconstructed by an ObjectInputStream.
306 *
307 * <p>Exceptions are thrown for problems with the OutputStream and for
308 * classes that should not be serialized. All exceptions are fatal to the
309 * OutputStream, which is left in an indeterminate state, and it is up to
310 * the caller to ignore or recover the stream state.
311 *
312 * @throws InvalidClassException Something is wrong with a class used by
313 * serialization.
314 * @throws NotSerializableException Some object to be serialized does not
315 * implement the java.io.Serializable interface.
316 * @throws IOException Any exception thrown by the underlying
317 * OutputStream.
318 */
319 public final void writeObject(Object obj) throws IOException {
320 if (enableOverride) {
321 writeObjectOverride(obj);
322 return;
323 }
324 try {
325 writeObject0(obj, false);
326 } catch (IOException ex) {
1295 private void writeOrdinaryObject(Object obj,
1296 ObjectStreamClass desc,
1297 boolean unshared)
1298 throws IOException
1299 {
1300 if (extendedDebugInfo) {
1301 debugInfoStack.push(
1302 (depth == 1 ? "root " : "") + "object (class \"" +
1303 obj.getClass().getName() + "\", " + obj.toString() + ")");
1304 }
1305 try {
1306 desc.checkSerialize();
1307
1308 bout.writeByte(TC_OBJECT);
1309 writeClassDesc(desc, false);
1310 handles.assign(unshared ? null : obj);
1311
1312 if (desc.isRecord()) {
1313 writeRecordData(obj, desc);
1314 } else if (desc.isExternalizable() && !desc.isProxy()) {
1315 writeExternalData((Externalizable) obj);
1316 } else {
1317 writeSerialData(obj, desc);
1318 }
1319 } finally {
1320 if (extendedDebugInfo) {
1321 debugInfoStack.pop();
1322 }
1323 }
1324 }
1325
1326 /**
1327 * Writes externalizable data of given object by invoking its
1328 * writeExternal() method.
1329 */
1330 private void writeExternalData(Externalizable obj) throws IOException {
1331 PutFieldImpl oldPut = curPut;
1332 curPut = null;
1333
1334 if (extendedDebugInfo) {
1343 bout.setBlockDataMode(true);
1344 obj.writeExternal(this);
1345 bout.setBlockDataMode(false);
1346 bout.writeByte(TC_ENDBLOCKDATA);
1347 }
1348 } finally {
1349 curContext = oldContext;
1350 if (extendedDebugInfo) {
1351 debugInfoStack.pop();
1352 }
1353 }
1354
1355 curPut = oldPut;
1356 }
1357
1358 /** Writes the record component values for the given record object. */
1359 private void writeRecordData(Object obj, ObjectStreamClass desc)
1360 throws IOException
1361 {
1362 assert obj.getClass().isRecord();
1363 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1364 if (slots.length != 1) {
1365 throw new InvalidClassException(
1366 "expected a single record slot length, but found: " + slots.length);
1367 }
1368
1369 defaultWriteFields(obj, desc); // #### seems unnecessary to use the accessors
1370 }
1371
1372 /**
1373 * Writes instance data for each serializable class of given object, from
1374 * superclass to subclass.
1375 */
1376 private void writeSerialData(Object obj, ObjectStreamClass desc)
1377 throws IOException
1378 {
1379 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1380 for (int i = 0; i < slots.length; i++) {
1381 ObjectStreamClass slotDesc = slots[i].desc;
1382 if (slotDesc.hasWriteObjectMethod()) {
1383 PutFieldImpl oldPut = curPut;
1384 curPut = null;
1385 SerialCallbackContext oldContext = curContext;
1386
1387 if (extendedDebugInfo) {
1388 debugInfoStack.push(
1389 "custom writeObject data (class \"" +
1390 slotDesc.getName() + "\")");
1391 }
1392 try {
1393 curContext = new SerialCallbackContext(obj, slotDesc);
1394 bout.setBlockDataMode(true);
1395 slotDesc.invokeWriteObject(obj, this);
1396 bout.setBlockDataMode(false);
1397 bout.writeByte(TC_ENDBLOCKDATA);
1398 } finally {
1399 curContext.setUsed();
1400 curContext = oldContext;
1401 if (extendedDebugInfo) {
|
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27 package java.io;
28
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.Objects;
33 import java.util.StringJoiner;
34
35 import jdk.internal.util.ByteArray;
36 import jdk.internal.access.JavaLangAccess;
37 import jdk.internal.access.SharedSecrets;
38
39 import static java.io.ObjectInputStream.TRACE;
40
41 import static jdk.internal.util.ModifiedUtf.putChar;
42 import static jdk.internal.util.ModifiedUtf.utfLen;
43
44 /**
45 * An ObjectOutputStream writes primitive data types and graphs of Java objects
46 * to an OutputStream. The objects can be read (reconstituted) using an
47 * ObjectInputStream. Persistent storage of objects can be accomplished by
48 * using a file for the stream. If the stream is a network socket stream, the
49 * objects can be reconstituted on another host or in another process.
50 *
51 * <p>Only objects that support the java.io.Serializable interface can be
52 * written to streams. The class of each serializable object is encoded
53 * including the class name and signature of the class, the values of the
54 * object's fields and arrays, and the closure of any other objects referenced
55 * from the initial objects.
56 *
57 * <p>The method writeObject is used to write an object to the stream. Any
58 * object, including Strings and arrays, is written with writeObject. Multiple
59 * objects or primitives can be written to the stream. The objects must be
60 * read back from the corresponding ObjectInputstream with the same types and
115 * implement the java.io.Serializable interface. Subclasses of Objects that
116 * are not serializable can be serializable. In this case the non-serializable
117 * class must have a no-arg constructor to allow its fields to be initialized.
118 * In this case it is the responsibility of the subclass to save and restore
119 * the state of the non-serializable class. It is frequently the case that the
120 * fields of that class are accessible (public, package, or protected) or that
121 * there are get and set methods that can be used to restore the state.
122 *
123 * <p>Serialization of an object can be prevented by implementing writeObject
124 * and readObject methods that throw the NotSerializableException. The
125 * exception will be caught by the ObjectOutputStream and abort the
126 * serialization process.
127 *
128 * <p>Implementing the Externalizable interface allows the object to assume
129 * complete control over the contents and format of the object's serialized
130 * form. The methods of the Externalizable interface, writeExternal and
131 * readExternal, are called to save and restore the objects state. When
132 * implemented by a class they can write and read their own state using all of
133 * the methods of ObjectOutput and ObjectInput. It is the responsibility of
134 * the objects to handle any versioning that occurs.
135 * Value classes implementing {@link Externalizable} cannot be serialized
136 * or deserialized, the value object is immutable and the state cannot be restored.
137 * Use {@link Serializable} {@code writeReplace} to delegate to another serializable
138 * object such as a record.
139 *
140 * Value objects cannot be {@code java.io.Externalizable}.
141 *
142 * <p>Enum constants are serialized differently than ordinary serializable or
143 * externalizable objects. The serialized form of an enum constant consists
144 * solely of its name; field values of the constant are not transmitted. To
145 * serialize an enum constant, ObjectOutputStream writes the string returned by
146 * the constant's name method. Like other serializable or externalizable
147 * objects, enum constants can function as the targets of back references
148 * appearing subsequently in the serialization stream. The process by which
149 * enum constants are serialized cannot be customized; any class-specific
150 * writeObject and writeReplace methods defined by enum types are ignored
151 * during serialization. Similarly, any serialPersistentFields or
152 * serialVersionUID field declarations are also ignored--all enum types have a
153 * fixed serialVersionUID of 0L.
154 *
155 * <p>Primitive data, excluding serializable fields and externalizable data, is
156 * written to the ObjectOutputStream in block-data records. A block data record
157 * is composed of a header and data. The block data header consists of a marker
158 * and the number of bytes to follow the header. Consecutive primitive data
159 * writes are merged into one block-data record. The blocking factor used for
160 * a block-data record will be 1024 bytes. Each block-data record will be
161 * filled up to 1024 bytes, or be written whenever there is a termination of
162 * block-data mode. Calls to the ObjectOutputStream methods writeObject,
163 * defaultWriteObject and writeFields initially terminate any existing
164 * block-data record.
165 *
166 * <a id="record-serialization"></a>
167 * <p>Records are serialized differently than ordinary serializable or externalizable
168 * objects, see <a href="ObjectInputStream.html#record-serialization">record serialization</a>.
169 *
170 * <a id="valueclass-serialization"></a>
171 * <p>Value classes are {@linkplain Serializable} through the use of the serialization proxy pattern.
172 * The serialization protocol does not support a standard serialized form for value classes.
173 * The value class delegates to a serialization proxy by supplying an alternate
174 * record or object to be serialized instead of the value class.
175 * When the proxy is deserialized it re-constructs the value object and returns the value object.
176 * For example,
177 * {@snippet lang="java" :
178 * value class ZipCode implements Serializable { // @highlight substring="value class"
179 * private static final long serialVersionUID = 1L;
180 * private int zipCode;
181 * public ZipCode(int zip) { this.zipCode = zip; }
182 * public int zipCode() { return zipCode; }
183 *
184 * public Object writeReplace() { // @highlight substring="writeReplace"
185 * return new ZipCodeProxy(zipCode);
186 * }
187 *
188 * private record ZipCodeProxy(int zipCode) implements Serializable {
189 * public Object readResolve() { // @highlight substring="readResolve"
190 * return new ZipCode(zipCode);
191 * }
192 * }
193 * }
194 * }
195 *
196 * @spec serialization/index.html Java Object Serialization Specification
197 * @author Mike Warres
198 * @author Roger Riggs
199 * @see java.io.DataOutput
200 * @see java.io.ObjectInputStream
201 * @see java.io.Serializable
202 * @see java.io.Externalizable
203 * @see <a href="{@docRoot}/../specs/serialization/output.html">
204 * <cite>Java Object Serialization Specification,</cite> Section 2, "Object Output Classes"</a>
205 * @since 1.1
206 */
207 public class ObjectOutputStream
208 extends OutputStream implements ObjectOutput, ObjectStreamConstants
209 {
210 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
211
212 /** filter stream for handling block data conversion */
213 private final BlockDataOutputStream bout;
214 /** obj -> wire handle map */
215 private final HandleTable handles;
322 case PROTOCOL_VERSION_1:
323 case PROTOCOL_VERSION_2:
324 protocol = version;
325 break;
326
327 default:
328 throw new IllegalArgumentException(
329 "unknown version: " + version);
330 }
331 }
332
333 /**
334 * Write the specified object to the ObjectOutputStream. The class of the
335 * object, the signature of the class, and the values of the non-transient
336 * and non-static fields of the class and all of its supertypes are
337 * written. Default serialization for a class can be overridden using the
338 * writeObject and the readObject methods. Objects referenced by this
339 * object are written transitively so that a complete equivalent graph of
340 * objects can be reconstructed by an ObjectInputStream.
341 *
342 * <p>Serialization and deserialization of value classes is described in
343 * {@linkplain ObjectOutputStream##valueclass-serialization value class serialization}.
344 *
345 * <p>Exceptions are thrown for problems with the OutputStream and for
346 * classes that should not be serialized. All exceptions are fatal to the
347 * OutputStream, which is left in an indeterminate state, and it is up to
348 * the caller to ignore or recover the stream state.
349 *
350 * @throws InvalidClassException Something is wrong with a class used by
351 * serialization.
352 * @throws NotSerializableException Some object to be serialized does not
353 * implement the java.io.Serializable interface.
354 * @throws IOException Any exception thrown by the underlying
355 * OutputStream.
356 */
357 public final void writeObject(Object obj) throws IOException {
358 if (enableOverride) {
359 writeObjectOverride(obj);
360 return;
361 }
362 try {
363 writeObject0(obj, false);
364 } catch (IOException ex) {
1333 private void writeOrdinaryObject(Object obj,
1334 ObjectStreamClass desc,
1335 boolean unshared)
1336 throws IOException
1337 {
1338 if (extendedDebugInfo) {
1339 debugInfoStack.push(
1340 (depth == 1 ? "root " : "") + "object (class \"" +
1341 obj.getClass().getName() + "\", " + obj.toString() + ")");
1342 }
1343 try {
1344 desc.checkSerialize();
1345
1346 bout.writeByte(TC_OBJECT);
1347 writeClassDesc(desc, false);
1348 handles.assign(unshared ? null : obj);
1349
1350 if (desc.isRecord()) {
1351 writeRecordData(obj, desc);
1352 } else if (desc.isExternalizable() && !desc.isProxy()) {
1353 if (desc.isValue())
1354 throw new InvalidClassException("Externalizable not valid for value class "
1355 + desc.forClass().getName());
1356 writeExternalData((Externalizable) obj);
1357 } else {
1358 writeSerialData(obj, desc);
1359 }
1360 } finally {
1361 if (extendedDebugInfo) {
1362 debugInfoStack.pop();
1363 }
1364 }
1365 }
1366
1367 /**
1368 * Writes externalizable data of given object by invoking its
1369 * writeExternal() method.
1370 */
1371 private void writeExternalData(Externalizable obj) throws IOException {
1372 PutFieldImpl oldPut = curPut;
1373 curPut = null;
1374
1375 if (extendedDebugInfo) {
1384 bout.setBlockDataMode(true);
1385 obj.writeExternal(this);
1386 bout.setBlockDataMode(false);
1387 bout.writeByte(TC_ENDBLOCKDATA);
1388 }
1389 } finally {
1390 curContext = oldContext;
1391 if (extendedDebugInfo) {
1392 debugInfoStack.pop();
1393 }
1394 }
1395
1396 curPut = oldPut;
1397 }
1398
1399 /** Writes the record component values for the given record object. */
1400 private void writeRecordData(Object obj, ObjectStreamClass desc)
1401 throws IOException
1402 {
1403 assert obj.getClass().isRecord();
1404 List<ObjectStreamClass.ClassDataSlot> slots = desc.getClassDataLayout();
1405 if (slots.size() != 1) {
1406 throw new InvalidClassException(
1407 "expected a single record slot length, but found: " + slots.size());
1408 }
1409
1410 defaultWriteFields(obj, desc); // #### seems unnecessary to use the accessors
1411 }
1412
1413 /**
1414 * Writes instance data for each serializable class of given object, from
1415 * superclass to subclass.
1416 */
1417 private void writeSerialData(Object obj, ObjectStreamClass desc)
1418 throws IOException
1419 {
1420 List<ObjectStreamClass.ClassDataSlot> slots = desc.getClassDataLayout();
1421 for (int i = 0; i < slots.size(); i++) {
1422 ObjectStreamClass slotDesc = slots.get(i).desc;
1423 if (slotDesc.hasWriteObjectMethod()) {
1424 PutFieldImpl oldPut = curPut;
1425 curPut = null;
1426 SerialCallbackContext oldContext = curContext;
1427
1428 if (extendedDebugInfo) {
1429 debugInfoStack.push(
1430 "custom writeObject data (class \"" +
1431 slotDesc.getName() + "\")");
1432 }
1433 try {
1434 curContext = new SerialCallbackContext(obj, slotDesc);
1435 bout.setBlockDataMode(true);
1436 slotDesc.invokeWriteObject(obj, this);
1437 bout.setBlockDataMode(false);
1438 bout.writeByte(TC_ENDBLOCKDATA);
1439 } finally {
1440 curContext.setUsed();
1441 curContext = oldContext;
1442 if (extendedDebugInfo) {
|