# HG changeset patch # User rriggs # Date 1378908981 14400 # Node ID 15c8e97d6a1492aa9af8effd4005e3e8653a4800 # Parent 4e10a58fa28fad072bdb94a3da771d3dd586c21f 8024164: JSR310 serialization should be described in details Summary: The serialized-form.html should specify the stream format for interoperability Reviewed-by: alanb diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/Duration.java --- a/jdk/src/share/classes/java/time/Duration.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/Duration.java Wed Sep 11 10:16:21 2013 -0400 @@ -74,7 +74,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; @@ -1299,8 +1299,9 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(1); // identifies this as a Duration + * out.writeByte(1); // identifies a Duration * out.writeLong(seconds); * out.writeInt(nanos); *@@ -1316,7 +1317,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/Instant.java --- a/jdk/src/share/classes/java/time/Instant.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/Instant.java Wed Sep 11 10:16:21 2013 -0400 @@ -76,7 +76,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -1317,8 +1317,9 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(2); // identifies this as an Instant + * out.writeByte(2); // identifies an Instant * out.writeLong(seconds); * out.writeInt(nanos); *@@ -1334,7 +1335,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/LocalDate.java --- a/jdk/src/share/classes/java/time/LocalDate.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/LocalDate.java Wed Sep 11 10:16:21 2013 -0400 @@ -78,7 +78,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.ChronoLocalDate; import java.time.chrono.Era; @@ -2019,8 +2019,9 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(3); // identifies this as a LocalDate + * out.writeByte(3); // identifies a LocalDate * out.writeInt(year); * out.writeByte(month); * out.writeByte(day); @@ -2037,7 +2038,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/LocalDateTime.java --- a/jdk/src/share/classes/java/time/LocalDateTime.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/LocalDateTime.java Wed Sep 11 10:16:21 2013 -0400 @@ -76,7 +76,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.ChronoLocalDateTime; import java.time.format.DateTimeFormatter; @@ -1953,8 +1953,9 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *- * out.writeByte(5); // identifies this as a LocalDateTime + * out.writeByte(5); // identifies a LocalDateTime * // the date excluding the one byte header * // the time excluding the one byte header *@@ -1970,7 +1971,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/LocalTime.java --- a/jdk/src/share/classes/java/time/LocalTime.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/LocalTime.java Wed Sep 11 10:16:21 2013 -0400 @@ -74,7 +74,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -1595,8 +1595,11 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData + * A twos-complement value indicates the remaining values are not in the stream + * and should be set to zero. *- * out.writeByte(4); // identifies this as a LocalTime + * out.writeByte(4); // identifies a LocalTime * if (nano == 0) { * if (second == 0) { * if (minute == 0) { @@ -1629,7 +1632,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/MonthDay.java --- a/jdk/src/share/classes/java/time/MonthDay.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/MonthDay.java Wed Sep 11 10:16:21 2013 -0400 @@ -68,7 +68,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.Chronology; import java.time.chrono.IsoChronology; @@ -744,9 +744,10 @@ //----------------------------------------------------------------------- /** * Writes the object using a - * dedicated serialized form. + * dedicated serialized form. + * @serialData *- * out.writeByte(13); // identifies this as a MonthDay + * out.writeByte(13); // identifies a MonthDay * out.writeByte(month); * out.writeByte(day); *@@ -762,7 +763,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/OffsetDateTime.java --- a/jdk/src/share/classes/java/time/OffsetDateTime.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/OffsetDateTime.java Wed Sep 11 10:16:21 2013 -0400 @@ -72,7 +72,7 @@ import java.io.InvalidObjectException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; @@ -1901,9 +1901,10 @@ //----------------------------------------------------------------------- /** * Writes the object using a - * dedicated serialized form. + * dedicated serialized form. + * @serialData *- * out.writeByte(10); // identifies this as a OffsetDateTime + * out.writeByte(10); // identifies a OffsetDateTime * out.writeObject(dateTime); * out.writeObject(offset); *@@ -1919,7 +1920,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/OffsetTime.java --- a/jdk/src/share/classes/java/time/OffsetTime.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/OffsetTime.java Wed Sep 11 10:16:21 2013 -0400 @@ -73,7 +73,7 @@ import java.io.InvalidObjectException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -1372,9 +1372,10 @@ //----------------------------------------------------------------------- /** * Writes the object using a - * dedicated serialized form. + * dedicated serialized form. + * @serialData *- * out.writeByte(9); // identifies this as a OffsetTime + * out.writeByte(9); // identifies a OffsetTime * out.writeObject(time); * out.writeObject(offset); *@@ -1390,7 +1391,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/Period.java --- a/jdk/src/share/classes/java/time/Period.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/Period.java Wed Sep 11 10:16:21 2013 -0400 @@ -70,7 +70,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.ChronoLocalDate; import java.time.chrono.Chronology; @@ -993,11 +993,12 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *- * out.writeByte(14); // identifies this as a Period + * out.writeByte(14); // identifies a Period * out.writeInt(years); * out.writeInt(months); - * out.writeInt(seconds); + * out.writeInt(days); ** * @return the instance of {@code Ser}, not null @@ -1011,7 +1012,7 @@ * @return never * @throws java.io.InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/Ser.java --- a/jdk/src/share/classes/java/time/Ser.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/Ser.java Wed Sep 11 10:16:21 2013 -0400 @@ -72,14 +72,14 @@ * byte flag would be used in order to specify an alternative version of the type format. * For example {@code LOCAL_DATE_TYPE_VERSION_2 = 21}. *- * In order to serialise the object it writes its byte and then calls back to the appropriate class where - * the serialisation is performed. In order to deserialise the object it read in the type byte, switching + * In order to serialize the object it writes its byte and then calls back to the appropriate class where + * the serialization is performed. In order to deserialize the object it read in the type byte, switching * in order to select which class to call back into. *
- * The serialisation format is determined on a per class basis. In the case of field based classes each + * The serialization format is determined on a per class basis. In the case of field based classes each * of the fields is written out with an appropriate size format in descending order of the field's size. For * example in the case of {@link LocalDate} year is written before month. Composite classes, such as - * {@link LocalDateTime} are serialised as one object. + * {@link LocalDateTime} are serialized as one object. *
* This class is mutable and should be created once per serialization. * @@ -133,6 +133,27 @@ //----------------------------------------------------------------------- /** * Implements the {@code Externalizable} interface to write the object. + * @serialData + * + * Each serializable class is mapped to a type that is the first byte + * in the stream. Refer to each class {@code writeReplace} + * serialized form for the value of the type and sequence of values for the type. + *
- * out.writeByte(11); // identifies this as a Year + * out.writeByte(11); // identifies a Year * out.writeInt(year); ** @@ -1097,7 +1098,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/YearMonth.java --- a/jdk/src/share/classes/java/time/YearMonth.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/YearMonth.java Wed Sep 11 10:16:21 2013 -0400 @@ -77,7 +77,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.Chronology; import java.time.chrono.IsoChronology; @@ -1205,9 +1205,10 @@ //----------------------------------------------------------------------- /** * Writes the object using a - * dedicated serialized form. + * dedicated serialized form. + * @serialData *
- * out.writeByte(12); // identifies this as a YearMonth + * out.writeByte(12); // identifies a YearMonth * out.writeInt(year); * out.writeByte(month); *@@ -1223,7 +1224,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/ZoneId.java --- a/jdk/src/share/classes/java/time/ZoneId.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/ZoneId.java Wed Sep 11 10:16:21 2013 -0400 @@ -63,6 +63,7 @@ import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; @@ -662,6 +663,15 @@ //----------------------------------------------------------------------- /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** * Outputs this zone as a {@code String}, using the ID. * * @return a string representation of this time-zone ID, not null @@ -675,9 +685,10 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(7); // identifies this as a ZoneId (not ZoneOffset) - * out.writeUTF(zoneId); + * out.writeByte(7); // identifies a ZoneId (not ZoneOffset) + * out.writeUTF(getId()); **
* When read back in, the {@code ZoneId} will be created as though using diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/ZoneOffset.java --- a/jdk/src/share/classes/java/time/ZoneOffset.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/ZoneOffset.java Wed Sep 11 10:16:21 2013 -0400 @@ -70,7 +70,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.temporal.ChronoField; import java.time.temporal.Temporal; @@ -740,12 +740,13 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(8); // identifies this as a ZoneOffset + * out.writeByte(8); // identifies a ZoneOffset * int offsetByte = totalSeconds % 900 == 0 ? totalSeconds / 900 : 127; * out.writeByte(offsetByte); * if (offsetByte == 127) { - * out.writeInt(totalSeconds); + * out.writeInt(totalSeconds); * } ** @@ -760,7 +761,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/ZoneRegion.java --- a/jdk/src/share/classes/java/time/ZoneRegion.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/ZoneRegion.java Wed Sep 11 10:16:21 2013 -0400 @@ -60,7 +60,7 @@ import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesException; @@ -181,8 +181,9 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(7); // identifies this as a ZoneId (not ZoneOffset) + * out.writeByte(7); // identifies a ZoneId (not ZoneOffset) * out.writeUTF(zoneId); ** @@ -197,7 +198,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/ZonedDateTime.java --- a/jdk/src/share/classes/java/time/ZonedDateTime.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/ZonedDateTime.java Wed Sep 11 10:16:21 2013 -0400 @@ -69,7 +69,7 @@ import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInput; -import java.io.ObjectStreamException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.chrono.ChronoZonedDateTime; import java.time.format.DateTimeFormatter; @@ -2192,9 +2192,10 @@ /** * Writes the object using a * dedicated serialized form. + * @serialData *
- * out.writeByte(6); // identifies this as a ZonedDateTime - * // the date-time excluding the one byte header + * out.writeByte(6); // identifies a ZonedDateTime + * // the dateTime excluding the one byte header * // the offset excluding the one byte header * // the zone ID excluding the one byte header *@@ -2210,7 +2211,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java --- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java Wed Sep 11 10:16:21 2013 -0400 @@ -94,7 +94,7 @@ * * @implSpec * This class is immutable and thread-safe. - * + * @serial * @param
+ * out.writeByte(2); // identifies a ChronoLocalDateTime + * out.writeObject(toLocalDate()); + * out.witeObject(toLocalTime()); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.CHRONO_LOCAL_DATE_TIME_TYPE, this); } @@ -411,7 +423,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java --- a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java Wed Sep 11 10:16:21 2013 -0400 @@ -98,6 +98,7 @@ * @implSpec * This class is immutable and thread-safe. * + * @serial Document the delegation of this class in the serialized-form specification. * @param
+ * out.writeByte(3); // identifies a ChronoZonedDateTime + * out.writeObject(toLocalDateTime()); + * out.writeObject(getOffset()); + * out.writeObject(getZone()); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.CHRONO_ZONE_DATE_TIME_TYPE, this); } @@ -330,7 +347,7 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/Chronology.java --- a/jdk/src/share/classes/java/time/chrono/Chronology.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/Chronology.java Wed Sep 11 10:16:21 2013 -0400 @@ -1258,14 +1258,15 @@ /** * Writes the Chronology using a * dedicated serialized form. + * @serialData *
- * out.writeByte(1); // identifies this as a Chronology + * out.writeByte(1); // identifies a Chronology * out.writeUTF(getId()); ** * @return the instance of {@code Ser}, not null */ - protected Object writeReplace() { + Object writeReplace() { return new Ser(Ser.CHRONO_TYPE, this); } @@ -1274,14 +1275,26 @@ * @return never * @throws InvalidObjectException always */ - private Object readResolve() throws ObjectStreamException { + private Object readResolve() throws InvalidObjectException { throw new InvalidObjectException("Deserialization via serialization delegate"); } + /** + * Write the Chronology id to the stream. + * @param out the output stream + * @throws IOException on any error during the write + */ void writeExternal(DataOutput out) throws IOException { out.writeUTF(getId()); } + /** + * Reads the Chronology id and creates the Chronology. + * @param in the input stream + * @return the Chronology + * @throws IOException on errors during the read + * @throws DateTimeException if the Chronology cannot be returned + */ static Chronology readExternal(DataInput in) throws IOException { String id = in.readUTF(); return Chronology.of(id); diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/HijrahChronology.java --- a/jdk/src/share/classes/java/time/chrono/HijrahChronology.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/HijrahChronology.java Wed Sep 11 10:16:21 2013 -0400 @@ -63,6 +63,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedActionException; @@ -217,11 +219,11 @@ /** * The Hijrah Calendar id. */ - private final String typeId; + private final transient String typeId; /** * The Hijrah calendarType. */ - private transient final String calendarType; + private final transient String calendarType; /** * Serialization version. */ @@ -236,7 +238,7 @@ * Flag to indicate the initialization of configuration data is complete. * @see #checkCalendarInit() */ - private volatile boolean initComplete; + private transient volatile boolean initComplete; /** * Array of epoch days indexed by Hijrah Epoch month. * Computed by {@link #loadCalendarData}. @@ -281,7 +283,7 @@ * A reference to the properties stored in * ${java.home}/lib/calendars.properties */ - private transient final static Properties calendarProperties; + private final transient static Properties calendarProperties; /** * Prefix of property names for Hijrah calendar variants. @@ -1073,4 +1075,30 @@ throw new IllegalArgumentException("date must be yyyy-MM-dd", ex); } } + + //----------------------------------------------------------------------- + /** + * Writes the Chronology using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(1); // identifies a Chronology + * out.writeUTF(getId()); + *+ * + * @return the instance of {@code Ser}, not null + */ + @Override + Object writeReplace() { + return super.writeReplace(); + } + + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/HijrahDate.java --- a/jdk/src/share/classes/java/time/chrono/HijrahDate.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/HijrahDate.java Wed Sep 11 10:16:21 2013 -0400 @@ -65,6 +65,7 @@ import static java.time.temporal.ChronoField.YEAR; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; @@ -118,7 +119,7 @@ /** * The Chronology of this HijrahDate. */ - private final HijrahChronology chrono; + private final transient HijrahChronology chrono; /** * The proleptic year. */ @@ -600,29 +601,41 @@ } //----------------------------------------------------------------------- + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(6); // identifies a HijrahDate + * out.writeObject(chrono); // the HijrahChronology variant + * out.writeInt(get(YEAR)); + * out.writeByte(get(MONTH_OF_YEAR)); + * out.writeByte(get(DAY_OF_MONTH)); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.HIJRAH_DATE_TYPE, this); } void writeExternal(ObjectOutput out) throws IOException { // HijrahChronology is implicit in the Hijrah_DATE_TYPE - out.writeObject(chrono); + out.writeObject(getChronology()); out.writeInt(get(YEAR)); out.writeByte(get(MONTH_OF_YEAR)); out.writeByte(get(DAY_OF_MONTH)); } - /** - * Replaces the date instance from the stream with a valid one. - * ReadExternal has already read the fields and created a new instance - * from the data. - * - * @return the resolved date, never null - */ - private Object readResolve() { - return this; - } - static HijrahDate readExternal(ObjectInput in) throws IOException, ClassNotFoundException { HijrahChronology chrono = (HijrahChronology) in.readObject(); int year = in.readInt(); diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/HijrahEra.java --- a/jdk/src/share/classes/java/time/chrono/HijrahEra.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/HijrahEra.java Wed Sep 11 10:16:21 2013 -0400 @@ -63,9 +63,6 @@ import static java.time.temporal.ChronoField.ERA; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; import java.time.DateTimeException; import java.time.temporal.ChronoField; import java.time.temporal.TemporalField; @@ -158,18 +155,4 @@ return Era.super.range(field); } - //----------------------------------------------------------------------- - private Object writeReplace() { - return new Ser(Ser.HIJRAH_ERA_TYPE, this); - } - - void writeExternal(DataOutput out) throws IOException { - out.writeByte(this.getValue()); - } - - static HijrahEra readExternal(DataInput in) throws IOException { - byte eraValue = in.readByte(); - return HijrahEra.of(eraValue); - } - } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/IsoChronology.java --- a/jdk/src/share/classes/java/time/chrono/IsoChronology.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/IsoChronology.java Wed Sep 11 10:16:21 2013 -0400 @@ -61,6 +61,8 @@ */ package java.time.chrono; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.ERA; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; @@ -563,4 +565,29 @@ return field.range(); } + //----------------------------------------------------------------------- + /** + * Writes the Chronology using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(1); // identifies a Chronology + * out.writeUTF(getId()); + *+ * + * @return the instance of {@code Ser}, not null + */ + @Override + Object writeReplace() { + return super.writeReplace(); + } + + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/JapaneseChronology.java --- a/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java Wed Sep 11 10:16:21 2013 -0400 @@ -56,6 +56,8 @@ */ package java.time.chrono; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.DAY_OF_YEAR; import static java.time.temporal.ChronoField.ERA; @@ -503,4 +505,29 @@ return dateYearDay(era, yoe, doy); // smart is same as strict } + //----------------------------------------------------------------------- + /** + * Writes the Chronology using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(1); // identifies a Chronology + * out.writeUTF(getId()); + *+ * + * @return the instance of {@code Ser}, not null + */ + @Override + Object writeReplace() { + return super.writeReplace(); + } + + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/JapaneseDate.java --- a/jdk/src/share/classes/java/time/chrono/JapaneseDate.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/JapaneseDate.java Wed Sep 11 10:16:21 2013 -0400 @@ -69,6 +69,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.Clock; import java.time.DateTimeException; @@ -129,7 +130,7 @@ /** * The underlying ISO local date. */ - private transient final LocalDate isoDate; + private final transient LocalDate isoDate; /** * The JapaneseEra of this date. */ @@ -689,6 +690,28 @@ } //----------------------------------------------------------------------- + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(4); // identifies a JapaneseDate + * out.writeInt(get(YEAR)); + * out.writeByte(get(MONTH_OF_YEAR)); + * out.writeByte(get(DAY_OF_MONTH)); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.JAPANESE_DATE_TYPE, this); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/JapaneseEra.java --- a/jdk/src/share/classes/java/time/chrono/JapaneseEra.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/JapaneseEra.java Wed Sep 11 10:16:21 2013 -0400 @@ -155,7 +155,7 @@ * The era value. * @serial */ - private final int eraValue; + private final transient int eraValue; // the first day of the era private final transient LocalDate since; @@ -371,6 +371,17 @@ } //----------------------------------------------------------------------- + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(5); // identifies a JapaneseEra + * out.writeInt(getValue()); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.JAPANESE_ERA_TYPE, this); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/MinguoChronology.java --- a/jdk/src/share/classes/java/time/chrono/MinguoChronology.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/MinguoChronology.java Wed Sep 11 10:16:21 2013 -0400 @@ -56,6 +56,8 @@ */ package java.time.chrono; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; import static java.time.temporal.ChronoField.PROLEPTIC_MONTH; import static java.time.temporal.ChronoField.YEAR; @@ -333,4 +335,29 @@ return (MinguoDate) super.resolveDate(fieldValues, resolverStyle); } + //----------------------------------------------------------------------- + /** + * Writes the Chronology using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(1); // identifies a Chronology + * out.writeUTF(getId()); + *+ * + * @return the instance of {@code Ser}, not null + */ + @Override + Object writeReplace() { + return super.writeReplace(); + } + + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/MinguoDate.java --- a/jdk/src/share/classes/java/time/chrono/MinguoDate.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/MinguoDate.java Wed Sep 11 10:16:21 2013 -0400 @@ -64,6 +64,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.Clock; import java.time.DateTimeException; @@ -106,7 +107,7 @@ /** * The underlying date. */ - private final LocalDate isoDate; + private final transient LocalDate isoDate; //----------------------------------------------------------------------- /** @@ -448,6 +449,28 @@ } //----------------------------------------------------------------------- + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(8); // identifies a MinguoDate + * out.writeInt(get(YEAR)); + * out.writeByte(get(MONTH_OF_YEAR)); + * out.writeByte(get(DAY_OF_MONTH)); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.MINGUO_DATE_TYPE, this); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/MinguoEra.java --- a/jdk/src/share/classes/java/time/chrono/MinguoEra.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/MinguoEra.java Wed Sep 11 10:16:21 2013 -0400 @@ -61,9 +61,6 @@ */ package java.time.chrono; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; import java.time.DateTimeException; /** @@ -155,18 +152,4 @@ return ordinal(); } - //----------------------------------------------------------------------- - private Object writeReplace() { - return new Ser(Ser.MINGUO_ERA_TYPE, this); - } - - void writeExternal(DataOutput out) throws IOException { - out.writeByte(this.getValue()); - } - - static MinguoEra readExternal(DataInput in) throws IOException { - byte eraValue = in.readByte(); - return MinguoEra.of(eraValue); - } - } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/Ser.java --- a/jdk/src/share/classes/java/time/chrono/Ser.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/Ser.java Wed Sep 11 10:16:21 2013 -0400 @@ -74,14 +74,14 @@ * byte flag would be used in order to specify an alternative version of the type format. * For example {@code CHRONO_TYPE_VERSION_2 = 21} *
- * In order to serialise the object it writes its byte and then calls back to the appropriate class where - * the serialisation is performed. In order to deserialise the object it read in the type byte, switching + * In order to serialize the object it writes its byte and then calls back to the appropriate class where + * the serialization is performed. In order to deserialize the object it read in the type byte, switching * in order to select which class to call back into. *
- * The serialisation format is determined on a per class basis. In the case of field based classes each + * The serialization format is determined on a per class basis. In the case of field based classes each * of the fields is written out with an appropriate size format in descending order of the field's size. For * example in the case of {@link LocalDate} year is written before month. Composite classes, such as - * {@link LocalDateTime} are serialised as one object. Enum classes are serialised using the index of their + * {@link LocalDateTime} are serialized as one object. Enum classes are serialized using the index of their * element. *
* This class is mutable and should be created once per serialization. @@ -102,11 +102,8 @@ static final byte JAPANESE_DATE_TYPE = 4; static final byte JAPANESE_ERA_TYPE = 5; static final byte HIJRAH_DATE_TYPE = 6; - static final byte HIJRAH_ERA_TYPE = 7; - static final byte MINGUO_DATE_TYPE = 8; - static final byte MINGUO_ERA_TYPE = 9; - static final byte THAIBUDDHIST_DATE_TYPE = 10; - static final byte THAIBUDDHIST_ERA_TYPE = 11; + static final byte MINGUO_DATE_TYPE = 7; + static final byte THAIBUDDHIST_DATE_TYPE = 8; /** The type being serialized. */ private byte type; @@ -133,6 +130,24 @@ //----------------------------------------------------------------------- /** * Implements the {@code Externalizable} interface to write the object. + * @serialData + * Each serializable class is mapped to a type that is the first byte + * in the stream. Refer to each class {@code writeReplace} + * serialized form for the value of the type and sequence of values for the type. + *
+ * out.writeByte(1); // identifies a Chronology + * out.writeUTF(getId()); + *+ * + * @return the instance of {@code Ser}, not null + */ + @Override + Object writeReplace() { + return super.writeReplace(); + } + + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java --- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistDate.java Wed Sep 11 10:16:21 2013 -0400 @@ -64,6 +64,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.Clock; import java.time.DateTimeException; @@ -106,7 +107,7 @@ /** * The underlying date. */ - private final LocalDate isoDate; + private final transient LocalDate isoDate; //----------------------------------------------------------------------- /** @@ -448,6 +449,28 @@ } //----------------------------------------------------------------------- + /** + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + *
+ * out.writeByte(10); // identifies a ThaiBuddhistDate + * out.writeInt(get(YEAR)); + * out.writeByte(get(MONTH_OF_YEAR)); + * out.writeByte(get(DAY_OF_MONTH)); + *+ * + * @return the instance of {@code Ser}, not null + */ private Object writeReplace() { return new Ser(Ser.THAIBUDDHIST_DATE_TYPE, this); } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java --- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistEra.java Wed Sep 11 10:16:21 2013 -0400 @@ -61,9 +61,6 @@ */ package java.time.chrono; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; import java.time.DateTimeException; /** @@ -155,18 +152,4 @@ return ordinal(); } - //----------------------------------------------------------------------- - private Object writeReplace() { - return new Ser(Ser.THAIBUDDHIST_ERA_TYPE, this); - } - - void writeExternal(DataOutput out) throws IOException { - out.writeByte(this.getValue()); - } - - static ThaiBuddhistEra readExternal(DataInput in) throws IOException { - byte eraValue = in.readByte(); - return ThaiBuddhistEra.of(eraValue); - } - } diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/zone/Ser.java --- a/jdk/src/share/classes/java/time/zone/Ser.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/zone/Ser.java Wed Sep 11 10:16:21 2013 -0400 @@ -119,9 +119,20 @@ //----------------------------------------------------------------------- /** * Implements the {@code Externalizable} interface to write the object. + * @serialData + * Each serializable class is mapped to a type that is the first byte + * in the stream. Refer to each class {@code writeReplace} + * serialized form for the value of the type and sequence of values for the type. + * + *
{@code * + * out.writeByte(2); // identifies a ZoneOffsetTransition + * out.writeEpochSec(toEpochSecond); + * out.writeOffset(offsetBefore); + * out.writeOfset(offsetAfter); + * } + ** @return the replacing object, not null */ private Object writeReplace() { diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java --- a/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java Wed Sep 11 10:16:21 2013 -0400 @@ -67,6 +67,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.DayOfWeek; import java.time.LocalDate; @@ -231,7 +232,56 @@ //----------------------------------------------------------------------- /** - * Uses a serialization delegate. + * Defend against malicious streams. + * @return never + * @throws InvalidObjectException always + */ + private Object readResolve() throws InvalidObjectException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + /** + * Writes the object using a + * dedicated serialized form. + * @serialData + * Refer to the serialized form of + * ZoneRules.writeReplace + * for the encoding of epoch seconds and offsets. + *
{@code + * + * out.writeByte(3); // identifies a ZoneOffsetTransition + * final int timeSecs = (timeEndOfDay ? 86400 : time.toSecondOfDay()); + * final int stdOffset = standardOffset.getTotalSeconds(); + * final int beforeDiff = offsetBefore.getTotalSeconds() - stdOffset; + * final int afterDiff = offsetAfter.getTotalSeconds() - stdOffset; + * final int timeByte = (timeSecs % 3600 == 0 ? (timeEndOfDay ? 24 : time.getHour()) : 31); + * final int stdOffsetByte = (stdOffset % 900 == 0 ? stdOffset / 900 + 128 : 255); + * final int beforeByte = (beforeDiff == 0 || beforeDiff == 1800 || beforeDiff == 3600 ? beforeDiff / 1800 : 3); + * final int afterByte = (afterDiff == 0 || afterDiff == 1800 || afterDiff == 3600 ? afterDiff / 1800 : 3); + * final int dowByte = (dow == null ? 0 : dow.getValue()); + * int b = (month.getValue() << 28) + // 4 bits + * ((dom + 32) << 22) + // 6 bits + * (dowByte << 19) + // 3 bits + * (timeByte << 14) + // 5 bits + * (timeDefinition.ordinal() << 12) + // 2 bits + * (stdOffsetByte << 4) + // 8 bits + * (beforeByte << 2) + // 2 bits + * afterByte; // 2 bits + * out.writeInt(b); + * if (timeByte == 31) { + * out.writeInt(timeSecs); + * } + * if (stdOffsetByte == 255) { + * out.writeInt(stdOffset); + * } + * if (beforeByte == 3) { + * out.writeInt(offsetBefore.getTotalSeconds()); + * } + * if (afterByte == 3) { + * out.writeInt(offsetAfter.getTotalSeconds()); + * } + * } + ** * @return the replacing object, not null */ diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/src/share/classes/java/time/zone/ZoneRules.java --- a/jdk/src/share/classes/java/time/zone/ZoneRules.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/src/share/classes/java/time/zone/ZoneRules.java Wed Sep 11 10:16:21 2013 -0400 @@ -64,6 +64,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.Serializable; import java.time.Duration; import java.time.Instant; @@ -145,7 +146,7 @@ /** * The map of recent transitions. */ - private final ConcurrentMap
{@code * + * out.writeByte(1); // identifies a ZoneRules + * out.writeInt(standardTransitions.length); + * for (long trans : standardTransitions) { + * Ser.writeEpochSec(trans, out); + * } + * for (ZoneOffset offset : standardOffsets) { + * Ser.writeOffset(offset, out); + * } + * out.writeInt(savingsInstantTransitions.length); + * for (long trans : savingsInstantTransitions) { + * Ser.writeEpochSec(trans, out); + * } + * for (ZoneOffset offset : wallOffsets) { + * Ser.writeOffset(offset, out); + * } + * out.writeByte(lastRules.length); + * for (ZoneOffsetTransitionRule rule : lastRules) { + * rule.writeExternal(out); + * } + * } + *+ *
+ * Epoch second values used for offsets are encoded in a variable + * length form to make the common cases put fewer bytes in the stream. + *
{@code + * + * static void writeEpochSec(long epochSec, DataOutput out) throws IOException { + * if (epochSec >= -4575744000L && epochSec < 10413792000L && epochSec % 900 == 0) { // quarter hours between 1825 and 2300 + * int store = (int) ((epochSec + 4575744000L) / 900); + * out.writeByte((store >>> 16) & 255); + * out.writeByte((store >>> 8) & 255); + * out.writeByte(store & 255); + * } else { + * out.writeByte(255); + * out.writeLong(epochSec); + * } + * } + * } + *+ *
+ * ZoneOffset values are encoded in a variable length form so the + * common cases put fewer bytes in the stream. + *
{@code + * + * static void writeOffset(ZoneOffset offset, DataOutput out) throws IOException { + * final int offsetSecs = offset.getTotalSeconds(); + * int offsetByte = offsetSecs % 900 == 0 ? offsetSecs / 900 : 127; // compress to -72 to +72 + * out.writeByte(offsetByte); + * if (offsetByte == 127) { + * out.writeInt(offsetSecs); + * } + * } + *} + ** @return the replacing object, not null */ private Object writeReplace() { diff -r 4e10a58fa28f -r 15c8e97d6a14 jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java --- a/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java Fri Sep 06 14:18:06 2013 -0700 +++ b/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java Wed Sep 11 10:16:21 2013 -0400 @@ -97,7 +97,9 @@ ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(chrono); out.close(); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + byte[] bytes = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked")