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 private static class Caches {
178 /** cache of subclass security audit results */
179 static final ClassValue<Boolean> subclassAudits =
180 new ClassValue<>() {
298 case PROTOCOL_VERSION_1:
299 case PROTOCOL_VERSION_2:
300 protocol = version;
301 break;
302
303 default:
304 throw new IllegalArgumentException(
305 "unknown version: " + version);
306 }
307 }
308
309 /**
310 * Write the specified object to the ObjectOutputStream. The class of the
311 * object, the signature of the class, and the values of the non-transient
312 * and non-static fields of the class and all of its supertypes are
313 * written. Default serialization for a class can be overridden using the
314 * writeObject and the readObject methods. Objects referenced by this
315 * object are written transitively so that a complete equivalent graph of
316 * objects can be reconstructed by an ObjectInputStream.
317 *
318 * <p>Exceptions are thrown for problems with the OutputStream and for
319 * classes that should not be serialized. All exceptions are fatal to the
320 * OutputStream, which is left in an indeterminate state, and it is up to
321 * the caller to ignore or recover the stream state.
322 *
323 * @throws InvalidClassException Something is wrong with a class used by
324 * serialization.
325 * @throws NotSerializableException Some object to be serialized does not
326 * implement the java.io.Serializable interface.
327 * @throws IOException Any exception thrown by the underlying
328 * OutputStream.
329 */
330 public final void writeObject(Object obj) throws IOException {
331 if (enableOverride) {
332 writeObjectOverride(obj);
333 return;
334 }
335 try {
336 writeObject0(obj, false);
337 } catch (IOException ex) {
1331 private void writeOrdinaryObject(Object obj,
1332 ObjectStreamClass desc,
1333 boolean unshared)
1334 throws IOException
1335 {
1336 if (extendedDebugInfo) {
1337 debugInfoStack.push(
1338 (depth == 1 ? "root " : "") + "object (class \"" +
1339 obj.getClass().getName() + "\", " + obj.toString() + ")");
1340 }
1341 try {
1342 desc.checkSerialize();
1343
1344 bout.writeByte(TC_OBJECT);
1345 writeClassDesc(desc, false);
1346 handles.assign(unshared ? null : obj);
1347
1348 if (desc.isRecord()) {
1349 writeRecordData(obj, desc);
1350 } else if (desc.isExternalizable() && !desc.isProxy()) {
1351 writeExternalData((Externalizable) obj);
1352 } else {
1353 writeSerialData(obj, desc);
1354 }
1355 } finally {
1356 if (extendedDebugInfo) {
1357 debugInfoStack.pop();
1358 }
1359 }
1360 }
1361
1362 /**
1363 * Writes externalizable data of given object by invoking its
1364 * writeExternal() method.
1365 */
1366 private void writeExternalData(Externalizable obj) throws IOException {
1367 PutFieldImpl oldPut = curPut;
1368 curPut = null;
1369
1370 if (extendedDebugInfo) {
1379 bout.setBlockDataMode(true);
1380 obj.writeExternal(this);
1381 bout.setBlockDataMode(false);
1382 bout.writeByte(TC_ENDBLOCKDATA);
1383 }
1384 } finally {
1385 curContext = oldContext;
1386 if (extendedDebugInfo) {
1387 debugInfoStack.pop();
1388 }
1389 }
1390
1391 curPut = oldPut;
1392 }
1393
1394 /** Writes the record component values for the given record object. */
1395 private void writeRecordData(Object obj, ObjectStreamClass desc)
1396 throws IOException
1397 {
1398 assert obj.getClass().isRecord();
1399 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1400 if (slots.length != 1) {
1401 throw new InvalidClassException(
1402 "expected a single record slot length, but found: " + slots.length);
1403 }
1404
1405 defaultWriteFields(obj, desc); // #### seems unnecessary to use the accessors
1406 }
1407
1408 /**
1409 * Writes instance data for each serializable class of given object, from
1410 * superclass to subclass.
1411 */
1412 private void writeSerialData(Object obj, ObjectStreamClass desc)
1413 throws IOException
1414 {
1415 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1416 for (int i = 0; i < slots.length; i++) {
1417 ObjectStreamClass slotDesc = slots[i].desc;
1418 if (slotDesc.hasWriteObjectMethod()) {
1419 PutFieldImpl oldPut = curPut;
1420 curPut = null;
1421 SerialCallbackContext oldContext = curContext;
1422
1423 if (extendedDebugInfo) {
1424 debugInfoStack.push(
1425 "custom writeObject data (class \"" +
1426 slotDesc.getName() + "\")");
1427 }
1428 try {
1429 curContext = new SerialCallbackContext(obj, slotDesc);
1430 bout.setBlockDataMode(true);
1431 slotDesc.invokeWriteObject(obj, this);
1432 bout.setBlockDataMode(false);
1433 bout.writeByte(TC_ENDBLOCKDATA);
1434 } finally {
1435 curContext.setUsed();
1436 curContext = oldContext;
1437 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 private static class Caches {
213 /** cache of subclass security audit results */
214 static final ClassValue<Boolean> subclassAudits =
215 new ClassValue<>() {
333 case PROTOCOL_VERSION_1:
334 case PROTOCOL_VERSION_2:
335 protocol = version;
336 break;
337
338 default:
339 throw new IllegalArgumentException(
340 "unknown version: " + version);
341 }
342 }
343
344 /**
345 * Write the specified object to the ObjectOutputStream. The class of the
346 * object, the signature of the class, and the values of the non-transient
347 * and non-static fields of the class and all of its supertypes are
348 * written. Default serialization for a class can be overridden using the
349 * writeObject and the readObject methods. Objects referenced by this
350 * object are written transitively so that a complete equivalent graph of
351 * objects can be reconstructed by an ObjectInputStream.
352 *
353 * <p>Serialization and deserialization of value classes is described in
354 * {@linkplain ObjectOutputStream##valueclass-serialization value class serialization}.
355 *
356 * <p>Exceptions are thrown for problems with the OutputStream and for
357 * classes that should not be serialized. All exceptions are fatal to the
358 * OutputStream, which is left in an indeterminate state, and it is up to
359 * the caller to ignore or recover the stream state.
360 *
361 * @throws InvalidClassException Something is wrong with a class used by
362 * serialization.
363 * @throws NotSerializableException Some object to be serialized does not
364 * implement the java.io.Serializable interface.
365 * @throws IOException Any exception thrown by the underlying
366 * OutputStream.
367 */
368 public final void writeObject(Object obj) throws IOException {
369 if (enableOverride) {
370 writeObjectOverride(obj);
371 return;
372 }
373 try {
374 writeObject0(obj, false);
375 } catch (IOException ex) {
1369 private void writeOrdinaryObject(Object obj,
1370 ObjectStreamClass desc,
1371 boolean unshared)
1372 throws IOException
1373 {
1374 if (extendedDebugInfo) {
1375 debugInfoStack.push(
1376 (depth == 1 ? "root " : "") + "object (class \"" +
1377 obj.getClass().getName() + "\", " + obj.toString() + ")");
1378 }
1379 try {
1380 desc.checkSerialize();
1381
1382 bout.writeByte(TC_OBJECT);
1383 writeClassDesc(desc, false);
1384 handles.assign(unshared ? null : obj);
1385
1386 if (desc.isRecord()) {
1387 writeRecordData(obj, desc);
1388 } else if (desc.isExternalizable() && !desc.isProxy()) {
1389 if (desc.isValue())
1390 throw new InvalidClassException("Externalizable not valid for value class "
1391 + desc.forClass().getName());
1392 writeExternalData((Externalizable) obj);
1393 } else {
1394 writeSerialData(obj, desc);
1395 }
1396 } finally {
1397 if (extendedDebugInfo) {
1398 debugInfoStack.pop();
1399 }
1400 }
1401 }
1402
1403 /**
1404 * Writes externalizable data of given object by invoking its
1405 * writeExternal() method.
1406 */
1407 private void writeExternalData(Externalizable obj) throws IOException {
1408 PutFieldImpl oldPut = curPut;
1409 curPut = null;
1410
1411 if (extendedDebugInfo) {
1420 bout.setBlockDataMode(true);
1421 obj.writeExternal(this);
1422 bout.setBlockDataMode(false);
1423 bout.writeByte(TC_ENDBLOCKDATA);
1424 }
1425 } finally {
1426 curContext = oldContext;
1427 if (extendedDebugInfo) {
1428 debugInfoStack.pop();
1429 }
1430 }
1431
1432 curPut = oldPut;
1433 }
1434
1435 /** Writes the record component values for the given record object. */
1436 private void writeRecordData(Object obj, ObjectStreamClass desc)
1437 throws IOException
1438 {
1439 assert obj.getClass().isRecord();
1440 List<ObjectStreamClass.ClassDataSlot> slots = desc.getClassDataLayout();
1441 if (slots.size() != 1) {
1442 throw new InvalidClassException(
1443 "expected a single record slot length, but found: " + slots.size());
1444 }
1445
1446 defaultWriteFields(obj, desc); // #### seems unnecessary to use the accessors
1447 }
1448
1449 /**
1450 * Writes instance data for each serializable class of given object, from
1451 * superclass to subclass.
1452 */
1453 private void writeSerialData(Object obj, ObjectStreamClass desc)
1454 throws IOException
1455 {
1456 List<ObjectStreamClass.ClassDataSlot> slots = desc.getClassDataLayout();
1457 for (int i = 0; i < slots.size(); i++) {
1458 ObjectStreamClass slotDesc = slots.get(i).desc;
1459 if (slotDesc.hasWriteObjectMethod()) {
1460 PutFieldImpl oldPut = curPut;
1461 curPut = null;
1462 SerialCallbackContext oldContext = curContext;
1463
1464 if (extendedDebugInfo) {
1465 debugInfoStack.push(
1466 "custom writeObject data (class \"" +
1467 slotDesc.getName() + "\")");
1468 }
1469 try {
1470 curContext = new SerialCallbackContext(obj, slotDesc);
1471 bout.setBlockDataMode(true);
1472 slotDesc.invokeWriteObject(obj, this);
1473 bout.setBlockDataMode(false);
1474 bout.writeByte(TC_ENDBLOCKDATA);
1475 } finally {
1476 curContext.setUsed();
1477 curContext = oldContext;
1478 if (extendedDebugInfo) {
|