diff --git a/src/java.base/share/classes/java/io/Externalizable.java b/src/java.base/share/classes/java/io/Externalizable.java index 137240ba089..84029fc5f3a 100644 --- a/src/java.base/share/classes/java/io/Externalizable.java +++ b/src/java.base/share/classes/java/io/Externalizable.java @@ -51,15 +51,9 @@ * constructor, then the readExternal method called. Serializable * objects are restored by reading them from an ObjectInputStream.
* - * An Externalizable object can designate a substitution object via + * An Externalizable instance can designate a substitution object via * 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. - *
+ * interface.
* * @see java.io.ObjectOutputStream * @see java.io.ObjectInputStream diff --git a/src/java.base/share/classes/java/io/InvalidClassException.java b/src/java.base/share/classes/java/io/InvalidClassException.java index 5045b0c4566..41d498fc1d2 100644 --- a/src/java.base/share/classes/java/io/InvalidClassException.java +++ b/src/java.base/share/classes/java/io/InvalidClassException.java @@ -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 @@ -28,19 +28,17 @@ /** * Thrown when the Serialization runtime detects one of the following * problems with a Class. - * * * @since 1.1 */ diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index c0030c04d65..e34224578ac 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -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. * *

Enum constants are deserialized differently than ordinary serializable or * externalizable objects. The serialized form of an enum constant consists @@ -241,9 +239,16 @@ * Java Object Serialization Specification, Section 1.13, * "Serialization of Records" for additional information. * - *

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. + *

+ *
+ *

{@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 + * + * {@code readResolve} to construct and return the expected value class + * instance. + *

+ *
* * @spec serialization/index.html Java Object Serialization Specification * @author Mike Warres @@ -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. * - *

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. - * *

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. * + *

+ *
+ *

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}. + *

+ *
+ * * @throws ClassNotFoundException Class of a serialized object cannot be * found. * @throws InvalidClassException Something is wrong with a class used by diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 59d9894ebb3..9d579d880ad 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -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}. * *

Enum constants are serialized differently than ordinary serializable or * externalizable objects. The serialized form of an enum constant consists @@ -163,35 +157,19 @@ * defaultWriteObject and writeFields initially terminate any existing * block-data record. * - * *

Records are serialized differently than ordinary serializable or externalizable * objects, see record serialization. * - * - *

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); - * } - * } - * } - * } + *

+ *
+ *

{@linkplain Class#isValue Value classes} that are not records cannot be + * serialized directly. To serialize an instance of a value class, the + * + * {@code writeReplace} 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. + *

+ *
* * @spec serialization/index.html Java Object Serialization Specification * @author Mike Warres @@ -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. * - *

Serialization and deserialization of value classes is described in - * {@linkplain ObjectOutputStream##valueclass-serialization value class serialization}. - * *

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. * + *

+ *
+ *

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}. + *

+ *
+ * * @throws InvalidClassException Something is wrong with a class used by * serialization. * @throws NotSerializableException Some object to be serialized does not diff --git a/src/java.base/share/classes/java/io/Serializable.java b/src/java.base/share/classes/java/io/Serializable.java index b348a000878..7d3b6087fc3 100644 --- a/src/java.base/share/classes/java/io/Serializable.java +++ b/src/java.base/share/classes/java/io/Serializable.java @@ -146,13 +146,16 @@ * handling methods discussed above, except {@code writeReplace}, * are ignored for record types.

* - * Value classes can implement {@code Serializble} and receive the treatment defined - * by the - * Java Object Serialization Specification, Section 1.14, - * "Serialization of Value Objects". 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.

+ *

+ *
+ *

{@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. + *

+ *
* * The serialization runtime associates with each serializable class a version * number, called a serialVersionUID, which is used during deserialization to