EnumSet.class serialization broken - twice

Peter Levart peter.levart at gmail.com
Tue Jun 18 12:31:02 UTC 2019


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