diff --git a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java index 74fdfc5a210..8414311e425 100644 --- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -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. + * + *

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

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 + * List, + * Map, or + * Set. + * 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"); diff --git a/jdk/src/java.base/share/classes/java/util/List.java b/jdk/src/java.base/share/classes/java/util/List.java index 4fa78032311..d4af1a31d49 100644 --- a/jdk/src/java.base/share/classes/java/util/List.java +++ b/jdk/src/java.base/share/classes/java/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -107,6 +107,9 @@ import java.util.function.UnaryOperator; * Factories are free to create new instances or reuse existing ones. Therefore, * identity-sensitive operations on these instances (reference equality ({@code ==}), * identity hash code, and synchronization) are unreliable and should be avoided. + *

  • They are serialized as specified on the + * Serialized Form + * page. * * *

    This interface is a member of the diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java index 7749845cbc5..9b71b0552b6 100644 --- a/jdk/src/java.base/share/classes/java/util/Map.java +++ b/jdk/src/java.base/share/classes/java/util/Map.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -133,6 +133,9 @@ import java.io.Serializable; * Factories are free to create new instances or reuse existing ones. Therefore, * identity-sensitive operations on these instances (reference equality ({@code ==}), * identity hash code, and synchronization) are unreliable and should be avoided. + *

  • They are serialized as specified on the + * Serialized Form + * page. * * *

    This interface is a member of the diff --git a/jdk/src/java.base/share/classes/java/util/Set.java b/jdk/src/java.base/share/classes/java/util/Set.java index 96f6f2d974d..15a594a5e28 100644 --- a/jdk/src/java.base/share/classes/java/util/Set.java +++ b/jdk/src/java.base/share/classes/java/util/Set.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -84,6 +84,9 @@ package java.util; * Factories are free to create new instances or reuse existing ones. Therefore, * identity-sensitive operations on these instances (reference equality ({@code ==}), * identity hash code, and synchronization) are unreliable and should be avoided. + *

  • They are serialized as specified on the + * Serialized Form + * page. * * *

    This interface is a member of the