JDK-8227368 : EnumSet.class serialization broken in JDK 9+
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 9,10,11,12,13,14
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2019-07-07
  • Updated: 2019-10-29
  • Resolved: 2019-07-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13 JDK 14
11.0.6-oracleFixed 13 b30Fixed 14Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
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

+@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, because their serialVersionUID value is always interpreted as 0 (which is understandable as they don't have a habit of declaring serialVersionUID fields).

Both of the above breaking 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. 
Comments
Fix Request This bug fix should be backported to JDK 11-update to help preserve serialization compatibility across JDK 8, JDK 11, and current JDKs. This incompatibility involves serialization of the EnumSet class, not instances of EnumSet. This case is fairly uncommon but it should nonetheless be fixed. A new test is added to verify that the serialVersionUID of EnumSet is the same value as it was in JDK 8. The JDK 13 fix changed the serialization specification for EnumSet. As such the fix cannot be backported to 11-update without changing the Java SE 11 specification or breaking conformance. An alternative fix has been developed that establishes the proper serialVersionUID value without need to change the specification. Review thread for 11-update backport: https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-July/001416.html
17-07-2019

URL: https://hg.openjdk.java.net/jdk/jdk13/rev/7fd4446c02ee User: plevart Date: 2019-07-13 10:44:26 +0000
13-07-2019

Discussion and review threads: http://mail.openjdk.java.net/pipermail/core-libs-dev/2019-June/060899.html http://mail.openjdk.java.net/pipermail/core-libs-dev/2019-July/061212.html
08-07-2019

Moving to P3. This is a fix for an incompatible change.
08-07-2019

Proposed fix: http://cr.openjdk.java.net/~plevart/jdk-dev/8227368_EnumSet.class_serialization/
07-07-2019