mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8133977: add specification for serialized forms
Reviewed-by: chegar, plevart, scolebourne
This commit is contained in:
parent
8fe063908e
commit
1dd84f024f
4 changed files with 124 additions and 11 deletions
|
@ -28,6 +28,7 @@ package java.util;
|
|||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -607,7 +608,10 @@ class ImmutableCollections {
|
|||
// ---------- Serialization Proxy ----------
|
||||
|
||||
/**
|
||||
* Serialization proxy class for immutable collections.
|
||||
* A unified serialization proxy class for the immutable collections.
|
||||
*
|
||||
* @serial
|
||||
* @since 9
|
||||
*/
|
||||
final class CollSer implements Serializable {
|
||||
private static final long serialVersionUID = 6309168927139932177L;
|
||||
|
@ -616,14 +620,114 @@ final class CollSer implements Serializable {
|
|||
static final int IMM_SET = 2;
|
||||
static final int IMM_MAP = 3;
|
||||
|
||||
private final int flags;
|
||||
private final Object[] array;
|
||||
/**
|
||||
* Indicates the type of collection that is serialized.
|
||||
* The low order 8 bits have the value 1 for an immutable
|
||||
* {@code List}, 2 for an immutable {@code Set}, and 3 for
|
||||
* an immutable {@code Map}. Any other value causes an
|
||||
* {@link InvalidObjectException} to be thrown. The high
|
||||
* order 24 bits are zero when an instance is serialized,
|
||||
* and they are ignored when an instance is deserialized.
|
||||
* They can thus be used by future implementations without
|
||||
* causing compatibility issues.
|
||||
*
|
||||
* <p>The tag value also determines the interpretation of the
|
||||
* transient {@code Object[] array} field.
|
||||
* For {@code List} and {@code Set}, the array's length is the size
|
||||
* of the collection, and the array contains the elements of the collection.
|
||||
* Null elements are not allowed. For {@code Set}, duplicate elements
|
||||
* are not allowed.
|
||||
*
|
||||
* <p>For {@code Map}, the array's length is twice the number of mappings
|
||||
* present in the map. The array length is necessarily even.
|
||||
* The array contains a succession of key and value pairs:
|
||||
* {@code k1, v1, k2, v2, ..., kN, vN.} Nulls are not allowed,
|
||||
* and duplicate keys are not allowed.
|
||||
*
|
||||
* @serial
|
||||
* @since 9
|
||||
*/
|
||||
private final int tag;
|
||||
|
||||
CollSer(int f, Object... a) {
|
||||
flags = f;
|
||||
/**
|
||||
* @serial
|
||||
* @since 9
|
||||
*/
|
||||
private transient Object[] array;
|
||||
|
||||
CollSer(int t, Object... a) {
|
||||
tag = t;
|
||||
array = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads objects from the stream and stores them
|
||||
* in the transient {@code Object[] array} field.
|
||||
*
|
||||
* @serialData
|
||||
* A nonnegative int, indicating the count of objects,
|
||||
* followed by that many objects.
|
||||
*
|
||||
* @param ois the ObjectInputStream from which data is read
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ClassNotFoundException if a serialized class cannot be loaded
|
||||
* @throws InvalidObjectException if the count is negative
|
||||
* @since 9
|
||||
*/
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
int len = ois.readInt();
|
||||
|
||||
if (len < 0) {
|
||||
throw new InvalidObjectException("negative length " + len);
|
||||
}
|
||||
|
||||
Object[] a = new Object[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
a[i] = ois.readObject();
|
||||
}
|
||||
|
||||
array = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes objects to the stream from
|
||||
* the transient {@code Object[] array} field.
|
||||
*
|
||||
* @serialData
|
||||
* A nonnegative int, indicating the count of objects,
|
||||
* followed by that many objects.
|
||||
*
|
||||
* @param oos the ObjectOutputStream to which data is written
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @since 9
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
oos.writeInt(array.length);
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
oos.writeObject(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an immutable collection from this proxy class.
|
||||
* The instance returned is created as if by calling one of the
|
||||
* static factory methods for
|
||||
* <a href="List.html#immutable">List</a>,
|
||||
* <a href="Map.html#immutable">Map</a>, or
|
||||
* <a href="Set.html#immutable">Set</a>.
|
||||
* This proxy class is the serial form for all immutable collection instances,
|
||||
* regardless of implementation type. This is necessary to ensure that the
|
||||
* existence of any particular implementation type is kept out of the
|
||||
* serialized form.
|
||||
*
|
||||
* @return a collection created from this proxy object
|
||||
* @throws InvalidObjectException if the tag value is illegal or if an exception
|
||||
* is thrown during creation of the collection
|
||||
* @throws ObjectStreamException if another serialization error has occurred
|
||||
* @since 9
|
||||
*/
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
try {
|
||||
if (array == null) {
|
||||
|
@ -631,8 +735,8 @@ final class CollSer implements Serializable {
|
|||
}
|
||||
|
||||
// use low order 8 bits to indicate "kind"
|
||||
// ignore high order bits
|
||||
switch (flags & 0xff) {
|
||||
// ignore high order 24 bits
|
||||
switch (tag & 0xff) {
|
||||
case IMM_LIST:
|
||||
return List.of(array);
|
||||
case IMM_SET:
|
||||
|
@ -646,7 +750,7 @@ final class CollSer implements Serializable {
|
|||
return new ImmutableCollections.MapN<>(array);
|
||||
}
|
||||
default:
|
||||
throw new InvalidObjectException(String.format("invalid flags 0x%x", flags));
|
||||
throw new InvalidObjectException(String.format("invalid flags 0x%x", tag));
|
||||
}
|
||||
} catch (NullPointerException|IllegalArgumentException ex) {
|
||||
InvalidObjectException ioe = new InvalidObjectException("invalid object");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue