EnumSet.class serialization broken - twice
Peter Levart
peter.levart at gmail.com
Tue Jun 18 14:32:03 UTC 2019
On 6/18/19 4:00 PM, Martin Buchholz wrote:
> Java Historian says:
> I was a reviewer for Effective Java 3rd Edition and EnumSet is the
> canonical example of the Serialization Proxy pattern,
> so I tried to make sure the pattern was implemented as perfectly as
> possible.
> 8192935: Fix EnumSet's SerializationProxy javadoc
> All of us who try to make java serialization work right have a mental
> model of the many things that might go wrong.
> Serialization of Class objects has never been part of my own mental
> model - I've only ever considered instances.
Perhaps the necessity for Class objects representing Serializable
classes to agree in sertialVersionUID is a bug in Java serialization
implementation? There's no such requirement for Class objects
representing non-Serializable classes and I don't see why this
requirement is there for Serializable classes. Could this requirement
simply be relaxed with no ill consequences?
Regards, Peter
>
>
> On Tue, Jun 18, 2019 at 5:32 AM Peter Levart <peter.levart at gmail.com
> <mailto:peter.levart at gmail.com>> wrote:
>
> Hi,
>
> I recently stumbled on an exception thrown when deserializing stream
> produced on JDK 8 and read with JDK 11. I narrowed the problem
> down to
> serialization/deserialization of a public EnumSet.class object. There
> were several changes made to EnumSet in the Mercurial history of jdk
> repo, but I think the following two broke the serialization:
>
> http://hg.openjdk.java.net/jdk/jdk/rev/d0e8542ef650
> http://hg.openjdk.java.net/jdk/jdk/rev/a7e13065a7a0
>
> It is interesting to note that before those two changes were made,
> there
> was a chance to fix the problem reported by newly added serial lint
> warnings. Unfortunately they were just silenced:
>
> http://hg.openjdk.java.net/jdk/jdk/rev/501d8479f798
>
> + at SuppressWarnings("serial") // No serialVersionUID due to usage of
> + // serial proxy pattern
>
> It is true that serialization of instances of Serializable classes is
> not broken by changes to them when they implement serial proxy
> pattern
> (i.e. writeReplace() method) even if they don't itself declare a
> private
> static final long serialVersionUID field, but this is not true of
> Class
> objects representing those Serializable classes. It is even more
> controversial that serialization of Class objects representing
> non-Serializable classes is never broken (which is understandable as
> they don't have a habit of declaring serialVersionUID fields).
>
> Both of the above braking changes were made post JDK 8 release, so
> deserialization of JDK 8 (and older) streams is affected in all
> JDK 9 +
> releases or vice versa.
>
> So, what shall be done. I suggest adding serialVersionUID field to
> EnumSet vith a value that corresponds to JDK 8 serialization
> format and
> later backport this change to JDK 11.
>
> What do you think?
>
>
> Regards, Peter
>
>
> PS: ImmutableCollections nested classes also implement serial proxy
> pattern and don't declare serialVersionUID fields, but they are not
> public, so it is less chance that Class objects representing them
> could
> be used in serial streams, although it is not impossible. For example:
>
> objectOutputStream.writeObject(Set.of().getClass());
>
More information about the core-libs-dev
mailing list