Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/java.base/share/classes/java/io/Externalizable.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,9 @@
* constructor, then the readExternal method called. Serializable
* objects are restored by reading them from an ObjectInputStream.<br>
*
* An Externalizable object can designate a substitution object via
* An Externalizable instance can designate a substitution object via
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to say anything special about value classes and Externalizable, so I just rolled this back to its JDK form.

(A value class can choose to implement Externalizable if it wants to, but it won't be able to do anything interesting, because all its fields are immutable. There's no integrity-related reason to have special rules or discussion here.)

* the writeReplace and readResolve methods documented in the Serializable
* interface. To control the serialized form of Records and Externalizable value classes
* the record or class uses {@link Serializable} {@code writeReplace}
* to delegate to another serializable or externalizable class and that delegate
* uses {@code readResolve} to supply the replacement on deserialization.
* Value classes implementing {@link Externalizable}
* and not using {@code writeReplace} are not supported.
* <br>
* interface.<br>
*
* @see java.io.ObjectOutputStream
* @see java.io.ObjectInputStream
Expand Down
24 changes: 11 additions & 13 deletions src/java.base/share/classes/java/io/InvalidClassException.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -28,19 +28,17 @@
/**
* Thrown when the Serialization runtime detects one of the following
* problems with a Class.
* <UL>
* <LI> The serial version of the class does not match that of the class
* descriptor read from the stream
* <LI> The class contains unknown datatypes
* <LI> The class does not have an accessible no-arg constructor
* <LI> The ObjectStreamClass of an enum constant does not represent
* an enum type
* <LI> Other conditions given in the <cite>Java Object Serialization
* <ul>
* <li>The serial version of the class does not match that of the class
* descriptor read from the stream
* <li>The class contains unknown datatypes
* <li>The class does not have an accessible no-arg constructor
* <li>The ObjectStreamClass of an enum constant does not represent
* an enum type
* <li>A {@linkplain Class#isValue value class} cannot be serialized
* <li> Other conditions given in the <cite>Java Object Serialization
* Specification</cite>
* <LI> A {@linkplain Class#isValue()} value class implements {@linkplain Serializable}
* but does not delegate to a serialization proxy using {@code writeReplace()}.
* <LI> A {@linkplain Class#isValue()} value class implements {@linkplain Externalizable}.
* </UL>
* </ul>
*
* @since 1.1
*/
Expand Down
32 changes: 19 additions & 13 deletions src/java.base/share/classes/java/io/ObjectInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@
* implemented by a class they can write and read their own state using all of
* the methods of ObjectOutput and ObjectInput. It is the responsibility of
* the objects to handle any versioning that occurs.
* Value objects cannot be `java.io.Externalizable` because value objects are
* immutable and `Externalizable.readExternal` is unable to modify the fields of the value.
*
* <p>Enum constants are deserialized differently than ordinary serializable or
* externalizable objects. The serialized form of an enum constant consists
Expand All @@ -241,9 +239,16 @@
* <cite>Java Object Serialization Specification,</cite> Section 1.13,
* "Serialization of Records"</a> for additional information.
*
* <p>Value classes are {@linkplain Serializable} through the use of the serialization proxy pattern.
* See {@linkplain ObjectOutputStream##valueclass-serialization value class serialization} for details.
* When the proxy is deserialized it re-constructs and returns the value object.
* <div class="preview-block">
* <div class="preview-comment">
* <p>{@linkplain Class#isValue Value classes} that are not records cannot be
* deserialized directly. To serialize an instance of a value class, a proxy
* object should be used instead. That object can then implement
* <a href="{@docRoot}/../specs/serialization/input.html#the-readresolve-method">
* {@code readResolve}</a> to construct and return the expected value class
* instance.
* </div>
* </div>
*
* @spec serialization/index.html Java Object Serialization Specification
* @author Mike Warres
Expand Down Expand Up @@ -435,19 +440,20 @@ protected ObjectInputStream() throws IOException {
* each object (regular or class) read to reconstruct the root object.
* See {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter} for details.
*
* <p>Serialization and deserialization of value classes is described in
* {@linkplain ObjectOutputStream##valueclass-serialization value class serialization}.
*
* @implSpec
* When enabled with {@code --enable-preview}, serialization and deserialization of
* Core Library value classes migrated from pre-JEP 401 identity classes is
* implementation specific.
*
* <p>Exceptions are thrown for problems with the InputStream and for
* classes that should not be deserialized. All exceptions are fatal to
* the InputStream and leave it in an indeterminate state; it is up to the
* caller to ignore or recover the stream state.
*
* <div class="preview-block">
* <div class="preview-comment">
* <p>An object in the stream that instantiates or extends a Serializable
* {@linkplain Class#isValue value class} can only be deserialized if
* it is a record or a boxed primitive value. Otherwise,
* {@code readObject} throws an {@code InvalidClassException}.
* </div>
* </div>
*
* @throws ClassNotFoundException Class of a serialized object cannot be
* found.
* @throws InvalidClassException Something is wrong with a class used by
Expand Down
55 changes: 20 additions & 35 deletions src/java.base/share/classes/java/io/ObjectOutputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,6 @@
* implemented by a class they can write and read their own state using all of
* the methods of ObjectOutput and ObjectInput. It is the responsibility of
* the objects to handle any versioning that occurs.
* Value classes implementing {@link Externalizable} cannot be serialized
* or deserialized, the value object is immutable and the state cannot be restored.
* Use {@link Serializable} {@code writeReplace} to delegate to another serializable
* object such as a record.
*
* Value objects cannot be {@code java.io.Externalizable}.
*
* <p>Enum constants are serialized differently than ordinary serializable or
* externalizable objects. The serialized form of an enum constant consists
Expand All @@ -163,35 +157,19 @@
* defaultWriteObject and writeFields initially terminate any existing
* block-data record.
*
* <a id="record-serialization"></a>
* <p>Records are serialized differently than ordinary serializable or externalizable
* objects, see <a href="ObjectInputStream.html#record-serialization">record serialization</a>.
*
* <a id="valueclass-serialization"></a>
* <p>Value classes are {@linkplain Serializable} through the use of the serialization proxy pattern.
* The serialization protocol does not support a standard serialized form for value classes.
* The value class delegates to a serialization proxy by supplying an alternate
* record or object to be serialized instead of the value class.
* When the proxy is deserialized it re-constructs the value object and returns the value object.
* For example,
* {@snippet lang="java" :
* value class ZipCode implements Serializable { // @highlight substring="value class"
* private static final long serialVersionUID = 1L;
* private int zipCode;
* public ZipCode(int zip) { this.zipCode = zip; }
* public int zipCode() { return zipCode; }
*
* public Object writeReplace() { // @highlight substring="writeReplace"
* return new ZipCodeProxy(zipCode);
* }
*
* private record ZipCodeProxy(int zipCode) implements Serializable {
* public Object readResolve() { // @highlight substring="readResolve"
* return new ZipCode(zipCode);
* }
* }
* }
* }
* <div class="preview-block">
* <div class="preview-comment">
* <p>{@linkplain Class#isValue Value classes} that are not records cannot be
* serialized directly. To serialize an instance of a value class, the
* <a href="{@docRoot}/../specs/serialization/output.html#the-writereplace-method">
* {@code writeReplace}</a> method can provide a proxy object instead. That
* object can then be serialized, and used to reconstruct the expected value
* class instance at deserialization time.
* </div>
* </div>
*
* @spec serialization/index.html Java Object Serialization Specification
* @author Mike Warres
Expand Down Expand Up @@ -339,14 +317,21 @@ public void useProtocolVersion(int version) throws IOException {
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*
* <p>Serialization and deserialization of value classes is described in
* {@linkplain ObjectOutputStream##valueclass-serialization value class serialization}.
*
* <p>Exceptions are thrown for problems with the OutputStream and for
* classes that should not be serialized. All exceptions are fatal to the
* OutputStream, which is left in an indeterminate state, and it is up to
* the caller to ignore or recover the stream state.
*
* <div class="preview-block">
* <div class="preview-comment">
* <p>An object that instantiates or extends a Serializable
* {@linkplain Class#isValue value class} can only be serialized if
* it is a record, or it implements {@code writeReplace}, or it is
* a boxed primitive value. Otherwise, {@code writeObject} throws an
* {@code InvalidClassException}.
* </div>
* </div>
*
* @throws InvalidClassException Something is wrong with a class used by
* serialization.
* @throws NotSerializableException Some object to be serialized does not
Expand Down
17 changes: 10 additions & 7 deletions src/java.base/share/classes/java/io/Serializable.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,16 @@
* handling methods discussed above, except {@code writeReplace},
* are ignored for record types.<p>
*
* Value classes can implement {@code Serializble} and receive the treatment defined
* by the <a href="{@docRoot}/../specs/serialization/serial-arch.html#serialization-of-value-objects">
* <cite>Java Object Serialization Specification,</cite> Section 1.14,
* "Serialization of Value Objects"</a>. Any declarations of the special
* handling methods discussed above, except {@code writeReplace},
* are ignored for value classes. Value classes implementing {@link Externalizable}
* and not using {@code writeReplace} are not supported.<p>
* <div class="preview-block">
* <div class="preview-comment">
* <p>{@linkplain Class#isValue Value classes} that are not records can
* implement {@code Serializable}, but cannot be serialized directly. Instead,
* the {@code writeReplace} method should be used to designate an alternative
* object for serialization. At deserialization time, the alternative object
* can implement {@code readResolve} to construct the expected value class
* instance.
* </div>
* </div>
*
* The serialization runtime associates with each serializable class a version
* number, called a serialVersionUID, which is used during deserialization to
Expand Down