1 /*
2 * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
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
143 * enum constants are serialized cannot be customized; any class-specific
144 * writeObject and writeReplace methods defined by enum types are ignored
145 * during serialization. Similarly, any serialPersistentFields or
146 * serialVersionUID field declarations are also ignored--all enum types have a
147 * fixed serialVersionUID of 0L.
148 *
149 * <p>Primitive data, excluding serializable fields and externalizable data, is
150 * written to the ObjectOutputStream in block-data records. A block data record
151 * is composed of a header and data. The block data header consists of a marker
152 * and the number of bytes to follow the header. Consecutive primitive data
153 * writes are merged into one block-data record. The blocking factor used for
154 * a block-data record will be 1024 bytes. Each block-data record will be
155 * filled up to 1024 bytes, or be written whenever there is a termination of
156 * block-data mode. Calls to the ObjectOutputStream methods writeObject,
157 * defaultWriteObject and writeFields initially terminate any existing
158 * block-data record.
159 *
160 * <p>Records are serialized differently than ordinary serializable or externalizable
161 * objects, see <a href="ObjectInputStream.html#record-serialization">record serialization</a>.
162 *
163 * @spec serialization/index.html Java Object Serialization Specification
164 * @author Mike Warres
165 * @author Roger Riggs
166 * @see java.io.DataOutput
167 * @see java.io.ObjectInputStream
168 * @see java.io.Serializable
169 * @see java.io.Externalizable
170 * @see <a href="{@docRoot}/../specs/serialization/output.html">
171 * <cite>Java Object Serialization Specification,</cite> Section 2, "Object Output Classes"</a>
172 * @since 1.1
173 */
174 public class ObjectOutputStream
175 extends OutputStream implements ObjectOutput, ObjectStreamConstants
176 {
177 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
178
179 /** filter stream for handling block data conversion */
180 private final BlockDataOutputStream bout;
181 /** obj -> wire handle map */
182 private final HandleTable handles;
294 default:
295 throw new IllegalArgumentException(
296 "unknown version: " + version);
297 }
298 }
299
300 /**
301 * Write the specified object to the ObjectOutputStream. The class of the
302 * object, the signature of the class, and the values of the non-transient
303 * and non-static fields of the class and all of its supertypes are
304 * written. Default serialization for a class can be overridden using the
305 * writeObject and the readObject methods. Objects referenced by this
306 * object are written transitively so that a complete equivalent graph of
307 * objects can be reconstructed by an ObjectInputStream.
308 *
309 * <p>Exceptions are thrown for problems with the OutputStream and for
310 * classes that should not be serialized. All exceptions are fatal to the
311 * OutputStream, which is left in an indeterminate state, and it is up to
312 * the caller to ignore or recover the stream state.
313 *
314 * @throws InvalidClassException Something is wrong with a class used by
315 * serialization.
316 * @throws NotSerializableException Some object to be serialized does not
317 * implement the java.io.Serializable interface.
318 * @throws IOException Any exception thrown by the underlying
319 * OutputStream.
320 */
321 public final void writeObject(Object obj) throws IOException {
322 if (enableOverride) {
323 writeObjectOverride(obj);
324 return;
325 }
326 try {
327 writeObject0(obj, false);
328 } catch (IOException ex) {
329 if (depth == 0) {
330 writeFatalException(ex);
331 }
332 throw ex;
333 }
1297 private void writeOrdinaryObject(Object obj,
1298 ObjectStreamClass desc,
1299 boolean unshared)
1300 throws IOException
1301 {
1302 if (extendedDebugInfo) {
1303 debugInfoStack.push(
1304 (depth == 1 ? "root " : "") + "object (class \"" +
1305 obj.getClass().getName() + "\", " + obj.toString() + ")");
1306 }
1307 try {
1308 desc.checkSerialize();
1309
1310 bout.writeByte(TC_OBJECT);
1311 writeClassDesc(desc, false);
1312 handles.assign(unshared ? null : obj);
1313
1314 if (desc.isRecord()) {
1315 writeRecordData(obj, desc);
1316 } else if (desc.isExternalizable() && !desc.isProxy()) {
1317 writeExternalData((Externalizable) obj);
1318 } else {
1319 writeSerialData(obj, desc);
1320 }
1321 } finally {
1322 if (extendedDebugInfo) {
1323 debugInfoStack.pop();
1324 }
1325 }
1326 }
1327
1328 /**
1329 * Writes externalizable data of given object by invoking its
1330 * writeExternal() method.
1331 */
1332 private void writeExternalData(Externalizable obj) throws IOException {
1333 PutFieldImpl oldPut = curPut;
1334 curPut = null;
1335
1336 if (extendedDebugInfo) {
|
1 /*
2 * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
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
143 * enum constants are serialized cannot be customized; any class-specific
144 * writeObject and writeReplace methods defined by enum types are ignored
145 * during serialization. Similarly, any serialPersistentFields or
146 * serialVersionUID field declarations are also ignored--all enum types have a
147 * fixed serialVersionUID of 0L.
148 *
149 * <p>Primitive data, excluding serializable fields and externalizable data, is
150 * written to the ObjectOutputStream in block-data records. A block data record
151 * is composed of a header and data. The block data header consists of a marker
152 * and the number of bytes to follow the header. Consecutive primitive data
153 * writes are merged into one block-data record. The blocking factor used for
154 * a block-data record will be 1024 bytes. Each block-data record will be
155 * filled up to 1024 bytes, or be written whenever there is a termination of
156 * block-data mode. Calls to the ObjectOutputStream methods writeObject,
157 * defaultWriteObject and writeFields initially terminate any existing
158 * block-data record.
159 *
160 * <p>Records are serialized differently than ordinary serializable or externalizable
161 * objects, see <a href="ObjectInputStream.html#record-serialization">record serialization</a>.
162 *
163 * <div class="preview-block">
164 * <div class="preview-comment">
165 * <p>{@linkplain Class#isValue Value classes} that are not records cannot be
166 * serialized directly. To serialize an instance of a value class, the
167 * <a href="{@docRoot}/../specs/serialization/output.html#the-writereplace-method">
168 * {@code writeReplace}</a> method can provide a proxy object instead. That
169 * object can then be serialized, and used to reconstruct the expected value
170 * class instance at deserialization time.
171 * </div>
172 * </div>
173 *
174 * @spec serialization/index.html Java Object Serialization Specification
175 * @author Mike Warres
176 * @author Roger Riggs
177 * @see java.io.DataOutput
178 * @see java.io.ObjectInputStream
179 * @see java.io.Serializable
180 * @see java.io.Externalizable
181 * @see <a href="{@docRoot}/../specs/serialization/output.html">
182 * <cite>Java Object Serialization Specification,</cite> Section 2, "Object Output Classes"</a>
183 * @since 1.1
184 */
185 public class ObjectOutputStream
186 extends OutputStream implements ObjectOutput, ObjectStreamConstants
187 {
188 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
189
190 /** filter stream for handling block data conversion */
191 private final BlockDataOutputStream bout;
192 /** obj -> wire handle map */
193 private final HandleTable handles;
305 default:
306 throw new IllegalArgumentException(
307 "unknown version: " + version);
308 }
309 }
310
311 /**
312 * Write the specified object to the ObjectOutputStream. The class of the
313 * object, the signature of the class, and the values of the non-transient
314 * and non-static fields of the class and all of its supertypes are
315 * written. Default serialization for a class can be overridden using the
316 * writeObject and the readObject methods. Objects referenced by this
317 * object are written transitively so that a complete equivalent graph of
318 * objects can be reconstructed by an ObjectInputStream.
319 *
320 * <p>Exceptions are thrown for problems with the OutputStream and for
321 * classes that should not be serialized. All exceptions are fatal to the
322 * OutputStream, which is left in an indeterminate state, and it is up to
323 * the caller to ignore or recover the stream state.
324 *
325 * <div class="preview-block">
326 * <div class="preview-comment">
327 * <p>An object that instantiates a concrete
328 * {@linkplain Class#isValue value class}, or that extends a
329 * Serializable abstract value class that declares instance fields,
330 * can only be serialized if it is a record, or it implements
331 * {@code writeReplace}, or it is a boxed primitive value.
332 * Otherwise, {@code writeObject} throws an
333 * {@code InvalidClassException}.
334 * </div>
335 * </div>
336 *
337 * @throws InvalidClassException Something is wrong with a class used by
338 * serialization.
339 * @throws NotSerializableException Some object to be serialized does not
340 * implement the java.io.Serializable interface.
341 * @throws IOException Any exception thrown by the underlying
342 * OutputStream.
343 */
344 public final void writeObject(Object obj) throws IOException {
345 if (enableOverride) {
346 writeObjectOverride(obj);
347 return;
348 }
349 try {
350 writeObject0(obj, false);
351 } catch (IOException ex) {
352 if (depth == 0) {
353 writeFatalException(ex);
354 }
355 throw ex;
356 }
1320 private void writeOrdinaryObject(Object obj,
1321 ObjectStreamClass desc,
1322 boolean unshared)
1323 throws IOException
1324 {
1325 if (extendedDebugInfo) {
1326 debugInfoStack.push(
1327 (depth == 1 ? "root " : "") + "object (class \"" +
1328 obj.getClass().getName() + "\", " + obj.toString() + ")");
1329 }
1330 try {
1331 desc.checkSerialize();
1332
1333 bout.writeByte(TC_OBJECT);
1334 writeClassDesc(desc, false);
1335 handles.assign(unshared ? null : obj);
1336
1337 if (desc.isRecord()) {
1338 writeRecordData(obj, desc);
1339 } else if (desc.isExternalizable() && !desc.isProxy()) {
1340 assert !desc.requiresDeserializer() : "Should be caught in checkSerialize";
1341 writeExternalData((Externalizable) obj);
1342 } else {
1343 writeSerialData(obj, desc);
1344 }
1345 } finally {
1346 if (extendedDebugInfo) {
1347 debugInfoStack.pop();
1348 }
1349 }
1350 }
1351
1352 /**
1353 * Writes externalizable data of given object by invoking its
1354 * writeExternal() method.
1355 */
1356 private void writeExternalData(Externalizable obj) throws IOException {
1357 PutFieldImpl oldPut = curPut;
1358 curPut = null;
1359
1360 if (extendedDebugInfo) {
|