changeset 8161:292d93f32aa1

8024164: JSR310 serialization should be described in details Summary: The serialized-form.html should specify the stream format for interoperability Reviewed-by: alanb
author rriggs
date Wed, 11 Sep 2013 10:16:21 -0400
parents 257de3e3a278
children 8b4aef582087
files src/share/classes/java/time/Duration.java src/share/classes/java/time/Instant.java src/share/classes/java/time/LocalDate.java src/share/classes/java/time/LocalDateTime.java src/share/classes/java/time/LocalTime.java src/share/classes/java/time/MonthDay.java src/share/classes/java/time/OffsetDateTime.java src/share/classes/java/time/OffsetTime.java src/share/classes/java/time/Period.java src/share/classes/java/time/Ser.java src/share/classes/java/time/Year.java src/share/classes/java/time/YearMonth.java src/share/classes/java/time/ZoneId.java src/share/classes/java/time/ZoneOffset.java src/share/classes/java/time/ZoneRegion.java src/share/classes/java/time/ZonedDateTime.java src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java src/share/classes/java/time/chrono/Chronology.java src/share/classes/java/time/chrono/HijrahChronology.java src/share/classes/java/time/chrono/HijrahDate.java src/share/classes/java/time/chrono/HijrahEra.java src/share/classes/java/time/chrono/IsoChronology.java src/share/classes/java/time/chrono/JapaneseChronology.java src/share/classes/java/time/chrono/JapaneseDate.java src/share/classes/java/time/chrono/JapaneseEra.java src/share/classes/java/time/chrono/MinguoChronology.java src/share/classes/java/time/chrono/MinguoDate.java src/share/classes/java/time/chrono/MinguoEra.java src/share/classes/java/time/chrono/Ser.java src/share/classes/java/time/chrono/ThaiBuddhistChronology.java src/share/classes/java/time/chrono/ThaiBuddhistDate.java src/share/classes/java/time/chrono/ThaiBuddhistEra.java src/share/classes/java/time/zone/Ser.java src/share/classes/java/time/zone/ZoneOffsetTransition.java src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java src/share/classes/java/time/zone/ZoneRules.java test/java/time/tck/java/time/chrono/TCKChronologySerialization.java
diffstat 38 files changed, 646 insertions(+), 166 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/time/Duration.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(1);  // identifies this as a Duration
+     *  out.writeByte(1);  // identifies a Duration
      *  out.writeLong(seconds);
      *  out.writeInt(nanos);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/Instant.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(2);  // identifies this as an Instant
+     *  out.writeByte(2);  // identifies an Instant
      *  out.writeLong(seconds);
      *  out.writeInt(nanos);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/LocalDate.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  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");
     }
 
--- a/src/share/classes/java/time/LocalDateTime.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(5);  // identifies this as a LocalDateTime
+     *  out.writeByte(5);  // identifies a LocalDateTime
      *  // the <a href="../../serialized-form.html#java.time.LocalDate">date</a> excluding the one byte header
      *  // the <a href="../../serialized-form.html#java.time.LocalTime">time</a> excluding the one byte header
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/LocalTime.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
+     * A twos-complement value indicates the remaining values are not in the stream
+     * and should be set to zero.
      * <pre>
-     *  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");
     }
 
--- a/src/share/classes/java/time/MonthDay.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(13);  // identifies this as a MonthDay
+     *  out.writeByte(13);  // identifies a MonthDay
      *  out.writeByte(month);
      *  out.writeByte(day);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/OffsetDateTime.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(10);  // identifies this as a OffsetDateTime
+     *  out.writeByte(10);  // identifies a OffsetDateTime
      *  out.writeObject(dateTime);
      *  out.writeObject(offset);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/OffsetTime.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(9);  // identifies this as a OffsetTime
+     *  out.writeByte(9);  // identifies a OffsetTime
      *  out.writeObject(time);
      *  out.writeObject(offset);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/Period.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  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);
      * </pre>
      *
      * @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");
     }
 
--- a/src/share/classes/java/time/Ser.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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}.
  * <p>
- * 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.
  * <p>
- * 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.
  * <p>
  * 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.
+     * <ul>
+     * <li><a href="../../serialized-form.html#java.time.Duration">Duration.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.Instant">Instant.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.LocalDate">LocalDate.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.LocalDateTime">LocalDateTime.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.LocalTime">LocalTime.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.MonthDay">MonthDay.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.OffsetTime">OffsetTime.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.OffsetDateTime">OffsetDateTime.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.Period">Period.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.Year">Year.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.YearMonth">YearMonth.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.ZoneId">ZoneId.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.ZoneOffset">ZoneOffset.writeReplace</a>
+     * <li><a href="../../serialized-form.html#java.time.ZonedDateTime">ZonedDateTime.writeReplace</a>
+     * </ul>
      *
      * @param out  the data stream to write to, not null
      */
@@ -194,6 +215,29 @@
     //-----------------------------------------------------------------------
     /**
      * Implements the {@code Externalizable} interface to read the object.
+     * @serialData
+     *
+     * The streamed type and parameters defined by the type's {@code writeReplace}
+     * method are read and passed to the corresponding static factory for the type
+     * to create a new instance.  That instance is returned as the de-serialized
+     * {@code Ser} object.
+     *
+     * <ul>
+     * <li><a href="../../serialized-form.html#java.time.Duration">Duration</a> - {@code Duration.ofSeconds(seconds, nanos);}
+     * <li><a href="../../serialized-form.html#java.time.Instant">Instant</a> - {@code Instant.ofEpochSecond(seconds, nanos);}
+     * <li><a href="../../serialized-form.html#java.time.LocalDate">LocalDate</a> - {@code LocalDate.of(year, month, day);}
+     * <li><a href="../../serialized-form.html#java.time.LocalDateTime">LocalDateTime</a> - {@code LocalDateTime.of(date, time);}
+     * <li><a href="../../serialized-form.html#java.time.LocalTime">LocalTime</a> - {@code LocalTime.of(hour, minute, second, nano);}
+     * <li><a href="../../serialized-form.html#java.time.MonthDay">MonthDay</a> - {@code MonthDay.of(month, day);}
+     * <li><a href="../../serialized-form.html#java.time.OffsetTime">OffsetTime</a> - {@code OffsetTime.of(time, offset);}
+     * <li><a href="../../serialized-form.html#java.time.OffsetDateTime">OffsetDateTime</a> - {@code OffsetDateTime.of(dateTime, offset);}
+     * <li><a href="../../serialized-form.html#java.time.Period">Period</a> - {@code Period.of(years, months, days);}
+     * <li><a href="../../serialized-form.html#java.time.Year">Year</a> - {@code Year.of(year);}
+     * <li><a href="../../serialized-form.html#java.time.YearMonth">YearMonth</a> - {@code YearMonth.of(year, month);}
+     * <li><a href="../../serialized-form.html#java.time.ZonedDateTime">ZonedDateTime</a> - {@code ZonedDateTime.ofLenient(dateTime, offset, zone);}
+     * <li><a href="../../serialized-form.html#java.time.ZoneId">ZoneId</a> - {@code ZoneId.of(id);}
+     * <li><a href="../../serialized-form.html#java.time.ZoneOffset">ZoneOffset</a> - {@code (offsetByte == 127 ? ZoneOffset.ofTotalSeconds(in.readInt()) : ZoneOffset.ofTotalSeconds(offsetByte * 900));}
+     * </ul>
      *
      * @param in  the data to read, not null
      */
--- a/src/share/classes/java/time/Year.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/src/share/classes/java/time/Year.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.chrono.Chronology;
 import java.time.chrono.IsoChronology;
@@ -1080,9 +1080,10 @@
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(11);  // identifies this as a Year
+     *  out.writeByte(11);  // identifies a Year
      *  out.writeInt(year);
      * </pre>
      *
@@ -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");
     }
 
--- a/src/share/classes/java/time/YearMonth.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(12);  // identifies this as a YearMonth
+     *  out.writeByte(12);  // identifies a YearMonth
      *  out.writeInt(year);
      *  out.writeByte(month);
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/ZoneId.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(7);  // identifies this as a ZoneId (not ZoneOffset)
-     *  out.writeUTF(zoneId);
+     *  out.writeByte(7);  // identifies a ZoneId (not ZoneOffset)
+     *  out.writeUTF(getId());
      * </pre>
      * <p>
      * When read back in, the {@code ZoneId} will be created as though using
--- a/src/share/classes/java/time/ZoneOffset.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  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);
      *  }
      * </pre>
      *
@@ -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");
     }
 
--- a/src/share/classes/java/time/ZoneRegion.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(7);  // identifies this as a ZoneId (not ZoneOffset)
+     *  out.writeByte(7);  // identifies a ZoneId (not ZoneOffset)
      *  out.writeUTF(zoneId);
      * </pre>
      *
@@ -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");
     }
 
--- a/src/share/classes/java/time/ZonedDateTime.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(6);  // identifies this as a ZonedDateTime
-     *  // the <a href="../../serialized-form.html#java.time.LocalDateTime">date-time</a> excluding the one byte header
+     *  out.writeByte(6);  // identifies a ZonedDateTime
+     *  // the <a href="../../serialized-form.html#java.time.LocalDateTime">dateTime</a> excluding the one byte header
      *  // the <a href="../../serialized-form.html#java.time.ZoneOffset">offset</a> excluding the one byte header
      *  // the <a href="../../serialized-form.html#java.time.ZoneId">zone ID</a> excluding the one byte header
      * </pre>
@@ -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");
     }
 
--- a/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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 <D> the concrete type for the date of this date-time
  * @since 1.8
  */
@@ -157,11 +157,11 @@
     /**
      * The date part.
      */
-    private final D date;
+    private final transient D date;
     /**
      * The time part.
      */
-    private final LocalTime time;
+    private final transient LocalTime time;
 
     //-----------------------------------------------------------------------
     /**
@@ -402,6 +402,18 @@
     }
 
     //-----------------------------------------------------------------------
+    /**
+     * Writes the ChronoLocalDateTime using a
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(2);              // identifies a ChronoLocalDateTime
+     *  out.writeObject(toLocalDate());
+     *  out.witeObject(toLocalTime());
+     * </pre>
+     *
+     * @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");
     }
 
--- a/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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 <D> the concrete type for the date of this date-time
  * @since 1.8
  */
@@ -112,15 +113,15 @@
     /**
      * The local date-time.
      */
-    private final ChronoLocalDateTimeImpl<D> dateTime;
+    private final transient ChronoLocalDateTimeImpl<D> dateTime;
     /**
      * The zone offset.
      */
-    private final ZoneOffset offset;
+    private final transient ZoneOffset offset;
     /**
      * The zone ID.
      */
-    private final ZoneId zone;
+    private final transient ZoneId zone;
 
     //-----------------------------------------------------------------------
     /**
@@ -222,6 +223,7 @@
     }
 
     //-----------------------------------------------------------------------
+    @Override
     public ZoneOffset getOffset() {
         return offset;
     }
@@ -256,10 +258,12 @@
         return dateTime;
     }
 
+    @Override
     public ZoneId getZone() {
         return zone;
     }
 
+    @Override
     public ChronoZonedDateTime<D> withZoneSameLocal(ZoneId zone) {
         return ofBest(dateTime, zone, offset);
     }
@@ -321,6 +325,19 @@
     }
 
     //-----------------------------------------------------------------------
+    /**
+     * Writes the ChronoZonedDateTime using a
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(3);                  // identifies a ChronoZonedDateTime
+     *  out.writeObject(toLocalDateTime());
+     *  out.writeObject(getOffset());
+     *  out.writeObject(getZone());
+     * </pre>
+     *
+     * @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");
     }
 
--- a/src/share/classes/java/time/chrono/Chronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
      * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
      * <pre>
-     *  out.writeByte(1);  // identifies this as a Chronology
+     *  out.writeByte(1);  // identifies a Chronology
      *  out.writeUTF(getId());
      * </pre>
      *
      * @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);
--- a/src/share/classes/java/time/chrono/HijrahChronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(1);     // identifies a Chronology
+     *  out.writeUTF(getId());
+     * </pre>
+     *
+     * @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");
+    }
 }
--- a/src/share/classes/java/time/chrono/HijrahDate.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  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));
+     * </pre>
+     *
+     * @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();
--- a/src/share/classes/java/time/chrono/HijrahEra.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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);
-    }
-
 }
--- a/src/share/classes/java/time/chrono/IsoChronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(1);     // identifies a Chronology
+     *  out.writeUTF(getId());
+     * </pre>
+     *
+     * @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");
+    }
 }
--- a/src/share/classes/java/time/chrono/JapaneseChronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(1);     // identifies a Chronology
+     *  out.writeUTF(getId());
+     * </pre>
+     *
+     * @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");
+    }
 }
--- a/src/share/classes/java/time/chrono/JapaneseDate.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(4);                 // identifies a JapaneseDate
+     *  out.writeInt(get(YEAR));
+     *  out.writeByte(get(MONTH_OF_YEAR));
+     *  out.writeByte(get(DAY_OF_MONTH));
+     * </pre>
+     *
+     * @return the instance of {@code Ser}, not null
+     */
     private Object writeReplace() {
         return new Ser(Ser.JAPANESE_DATE_TYPE, this);
     }
--- a/src/share/classes/java/time/chrono/JapaneseEra.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(5);        // identifies a JapaneseEra
+     *  out.writeInt(getValue());
+     * </pre>
+     *
+     * @return the instance of {@code Ser}, not null
+     */
     private Object writeReplace() {
         return new Ser(Ser.JAPANESE_ERA_TYPE, this);
     }
--- a/src/share/classes/java/time/chrono/MinguoChronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(1);     // identifies a Chronology
+     *  out.writeUTF(getId());
+     * </pre>
+     *
+     * @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");
+    }
 }
--- a/src/share/classes/java/time/chrono/MinguoDate.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(8);                 // identifies a MinguoDate
+     *  out.writeInt(get(YEAR));
+     *  out.writeByte(get(MONTH_OF_YEAR));
+     *  out.writeByte(get(DAY_OF_MONTH));
+     * </pre>
+     *
+     * @return the instance of {@code Ser}, not null
+     */
     private Object writeReplace() {
         return new Ser(Ser.MINGUO_DATE_TYPE, this);
     }
--- a/src/share/classes/java/time/chrono/MinguoEra.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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);
-    }
-
 }
--- a/src/share/classes/java/time/chrono/Ser.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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}
  * <p>
- * 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.
  * <p>
- * 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.
  * <p>
  * 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.
+     * <ul>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.HijrahChronology">HijrahChronology.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.IsoChronology">IsoChronology.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseChronology">JapaneseChronology.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.MinguoChronology">MinguoChronology.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ThaiBuddhistChronology">ThaiBuddhistChronology.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ChronoLocalDateTimeImpl">ChronoLocalDateTime.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ChronoZonedDateTimeImpl">ChronoZonedDateTime.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseDate">JapaneseDate.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseEra">JapaneseEra.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.HijrahDate">HijrahDate.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.MinguoDate">MinguoDate.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ThaiBuddhistDate">ThaiBuddhistDate.writeReplace</a>
+     * </ul>
      *
      * @param out  the data stream to write to, not null
      */
@@ -162,21 +177,12 @@
             case HIJRAH_DATE_TYPE:
                 ((HijrahDate) object).writeExternal(out);
                 break;
-            case HIJRAH_ERA_TYPE:
-                ((HijrahEra) object).writeExternal(out);
-                break;
             case MINGUO_DATE_TYPE:
                 ((MinguoDate) object).writeExternal(out);
                 break;
-            case MINGUO_ERA_TYPE:
-                ((MinguoEra) object).writeExternal(out);
-                break;
             case THAIBUDDHIST_DATE_TYPE:
                 ((ThaiBuddhistDate) object).writeExternal(out);
                 break;
-            case THAIBUDDHIST_ERA_TYPE:
-                ((ThaiBuddhistEra) object).writeExternal(out);
-                break;
             default:
                 throw new InvalidClassException("Unknown serialized type");
         }
@@ -185,8 +191,28 @@
     //-----------------------------------------------------------------------
     /**
      * Implements the {@code Externalizable} interface to read the object.
+     * @serialData
+     * The streamed type and parameters defined by the type's {@code writeReplace}
+     * method are read and passed to the corresponding static factory for the type
+     * to create a new instance.  That instance is returned as the de-serialized
+     * {@code Ser} object.
      *
-     * @param in  the data to read, not null
+     * <ul>
+     * <li><a href="../../../serialized-form.html#java.time.chrono.HijrahChronology">HijrahChronology</a> - Chronology.of(id)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.IsoChronology">IsoChronology</a> - Chronology.of(id)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseChronology">JapaneseChronology</a> - Chronology.of(id)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.MinguoChronology">MinguoChronology</a> - Chronology.of(id)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ThaiBuddhistChronology">ThaiBuddhistChronology</a> - Chronology.of(id)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ChronoLocalDateTimeImpl">ChronoLocalDateTime</a> - date.atTime(time)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ChronoZonedDateTimeImpl">ChronoZonedDateTime</a> - dateTime.atZone(offset).withZoneSameLocal(zone)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseDate">JapaneseDate</a> - JapaneseChronology.INSTANCE.date(year, month, dayOfMonth)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.JapaneseEra">JapaneseEra</a> - JapaneseEra.of(eraValue)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.HijrahDate">HijrahDate</a> - HijrahChronology chrono.date(year, month, dayOfMonth)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.MinguoDate">MinguoDate</a> - MinguoChronology.INSTANCE.date(year, month, dayOfMonth)
+     * <li><a href="../../../serialized-form.html#java.time.chrono.ThaiBuddhistDate">ThaiBuddhistDate</a> - ThaiBuddhistChronology.INSTANCE.date(year, month, dayOfMonth)
+     * </ul>
+     *
+     * @param in  the data stream to read from, not null
      */
     @Override
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
@@ -207,11 +233,8 @@
             case JAPANESE_DATE_TYPE:  return JapaneseDate.readExternal(in);
             case JAPANESE_ERA_TYPE: return JapaneseEra.readExternal(in);
             case HIJRAH_DATE_TYPE: return HijrahDate.readExternal(in);
-            case HIJRAH_ERA_TYPE: return HijrahEra.readExternal(in);
             case MINGUO_DATE_TYPE: return MinguoDate.readExternal(in);
-            case MINGUO_ERA_TYPE: return MinguoEra.readExternal(in);
             case THAIBUDDHIST_DATE_TYPE: return ThaiBuddhistDate.readExternal(in);
-            case THAIBUDDHIST_ERA_TYPE: return ThaiBuddhistEra.readExternal(in);
             default: throw new StreamCorruptedException("Unknown serialized type");
         }
     }
--- a/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/src/share/classes/java/time/chrono/ThaiBuddhistChronology.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;
 
@@ -369,4 +371,29 @@
         return (ThaiBuddhistDate) super.resolveDate(fieldValues, resolverStyle);
     }
 
+    //-----------------------------------------------------------------------
+    /**
+     * Writes the Chronology using a
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(1);     // identifies a Chronology
+     *  out.writeUTF(getId());
+     * </pre>
+     *
+     * @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");
+    }
 }
--- a/src/share/classes/java/time/chrono/ThaiBuddhistDate.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre>
+     *  out.writeByte(10);                // identifies a ThaiBuddhistDate
+     *  out.writeInt(get(YEAR));
+     *  out.writeByte(get(MONTH_OF_YEAR));
+     *  out.writeByte(get(DAY_OF_MONTH));
+     * </pre>
+     *
+     * @return the instance of {@code Ser}, not null
+     */
     private Object writeReplace() {
         return new Ser(Ser.THAIBUDDHIST_DATE_TYPE, this);
     }
--- a/src/share/classes/java/time/chrono/ThaiBuddhistEra.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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);
-    }
-
 }
--- a/src/share/classes/java/time/zone/Ser.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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.
+     *
+     * <ul>
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneRules">ZoneRules.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransition">ZoneOffsetTransition.writeReplace</a>
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransitionRule">ZoneOffsetTransitionRule.writeReplace</a>
+     * </ul>
      *
      * @param out  the data stream to write to, not null
      */
+    @Override
     public void writeExternal(ObjectOutput out) throws IOException {
         writeInternal(type, object, out);
     }
@@ -150,9 +161,23 @@
     //-----------------------------------------------------------------------
     /**
      * Implements the {@code Externalizable} interface to read the object.
+     * @serialData
+     * The streamed type and parameters defined by the type's {@code writeReplace}
+     * method are read and passed to the corresponding static factory for the type
+     * to create a new instance.  That instance is returned as the de-serialized
+     * {@code Ser} object.
      *
+     * <ul>
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneRules">ZoneRules</a>
+     * - {@code ZoneRules.of(standardTransitions, standardOffsets, savingsInstantTransitions, wallOffsets, lastRules);}
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransition">ZoneOffsetTransition</a>
+     * - {@code ;}
+     * <li><a href="../../../serialized-form.html#java.time.zone.ZoneOffsetTransitionRule">ZoneOffsetTransitionRule</a>
+     * - {@code ;}
+     * </ul>
      * @param in  the data to read, not null
      */
+    @Override
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
         type = in.readByte();
         object = readInternal(type, in);
--- a/src/share/classes/java/time/zone/ZoneOffsetTransition.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/src/share/classes/java/time/zone/ZoneOffsetTransition.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;
@@ -170,8 +171,29 @@
 
     //-----------------------------------------------------------------------
     /**
-     * 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
+     * <a href="../../../serialized-form.html#java.time.zone.Ser">dedicated serialized form</a>.
+     * @serialData
+     * Refer to the serialized form of
+     * <a href="../../../serialized-form.html#java.time.zone.ZoneRules">ZoneRules.writeReplace</a>
+     * for the encoding of epoch seconds and offsets.
+     * <pre style="font-size:1.0em">{@code
      *
+     *   out.writeByte(2);                // identifies a ZoneOffsetTransition
+     *   out.writeEpochSec(toEpochSecond);
+     *   out.writeOffset(offsetBefore);
+     *   out.writeOfset(offsetAfter);
+     * }
+     * </pre>
      * @return the replacing object, not null
      */
     private Object writeReplace() {
--- a/src/share/classes/java/time/zone/ZoneOffsetTransitionRule.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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
+     * <a href="../../../serialized-form.html#java.time.zone.Ser">dedicated serialized form</a>.
+     * @serialData
+     * Refer to the serialized form of
+     * <a href="../../../serialized-form.html#java.time.zone.ZoneRules">ZoneRules.writeReplace</a>
+     * for the encoding of epoch seconds and offsets.
+     * <pre style="font-size:1.0em">{@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());
+     *      }
+     * }
+     * </pre>
      *
      * @return the replacing object, not null
      */
--- a/src/share/classes/java/time/zone/ZoneRules.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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<Integer, ZoneOffsetTransition[]> lastRulesCache =
+    private final transient ConcurrentMap<Integer, ZoneOffsetTransition[]> lastRulesCache =
                 new ConcurrentHashMap<Integer, ZoneOffsetTransition[]>();
     /**
      * The zero-length long array.
@@ -315,8 +316,74 @@
     }
 
     /**
-     * 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
+     * <a href="../../../serialized-form.html#java.time.zone.Ser">dedicated serialized form</a>.
+     * @serialData
+     * <pre style="font-size:1.0em">{@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);
+     *   }
+     * }
+     * </pre>
+     * <p>
+     * Epoch second values used for offsets are encoded in a variable
+     * length form to make the common cases put fewer bytes in the stream.
+     * <pre style="font-size:1.0em">{@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);
+     *      }
+     *  }
+     * }
+     * </pre>
+     * <p>
+     * ZoneOffset values are encoded in a variable length form so the
+     * common cases put fewer bytes in the stream.
+     * <pre style="font-size:1.0em">{@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);
+     *     }
+     * }
+     *}
+     * </pre>
      * @return the replacing object, not null
      */
     private Object writeReplace() {
--- a/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java	Fri Sep 06 14:18:06 2013 -0700
+++ b/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")