JDK-6368570 : waive serialVersionUID matching requirement for interfaces
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.io:serialization
  • Affected Version: 5.0
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2006-01-04
  • Updated: 2019-07-15
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
The serialVersionUID of an interface that extends java.io.Serializable is actually significant: it DOES NOT matter when serializing an instance of the interface (in that case, only the serialVersionUID of the object's class and its serializable superclasses must match between the classes used to serialize the object and the classes used to deserialize the object), but it DOES matter when serializing the Class object for the interface: if the interface used to serialize the Class object had a different serialVersionUID than the interface resolved to deserialize it, the deserialization operation will fail with a java.io.InvalidClassException.  This requirement that the serialVersionUIDs of interfaces match is problematic and should be waived, similar to how it is waived for array classes.

Little purpose is served by enforcing matching serialVersionUIDs for interfaces: the serialized form of their Class objects cannot evolve (in an interface-specific way), and they do not affect the serialized forms of their instances.  One might argue that serialVersionUIDs could be used to detect incompatible evolution of an interface's contract, but only for interfaces that extend Serializable anyway (which are intentionally rare), and the merits of that means of enforcement are at best controversial.

Furthermore, the usual technique to keep serialVersionUIDs matching for evolved classes-- declaring an explicit serialVersionUID-- is highly problematic for interfaces, because interface members must be public; therefore, an interface's serialVersionUID is necessarily inherited as a public field by all subtypes in which it is not hidden.  (See the Evaluation of JDK-4228568 for more discussion about this problem.)

Fortunately, having an interface extend Serializable is discouraged as a matter of style, and interfaces are much less likely than classes to be evolved in ways that affect the fragile default serialVersionUID computation algorithm, so this issue hasn't been much of a practical problem so far (JDK-4228568 notwithstanding)-- but challenging cases could arise in the future, and it would seem prudent to standardize waiving the matching requirement before such cases arise.

Comments
Note that while JEP 213: "Milling Project Coin" added support for source-level private methods in interfaces (JDK-8071453), it did *not* allow for source-level private static final fields, the most appropriate kind of field to use for a serialVersionUID. In other words, as of the JDK 14 version of the language, a serialVersionUID for an interface type would still need to be public rather than private.
15-07-2019

SUGGESTED FIX For the specification, say that the requirement for matching serialVersionUID values is waived for interfaces, like it is already specified to be waived for array classes-- see section 4.6 and the doc for ObjectInputStream.resolveClass. For the implementation: in ObjectStreamClass.java, in the initNonProxy method, where serialVersionUID matching is enforced: if (serializable == localDesc.serializable && !cl.isArray() && suid.longValue() != localDesc.getSerialVersionUID()) { throw new InvalidClassException(localDesc.name, exclude the case where "cl.isInterface()" just like the "cl.isArray()" case is excluded, perhaps like this: if (serializable == localDesc.serializable && !cl.isArray() && !cl.isInterface() && suid.longValue() != localDesc.getSerialVersionUID()) { throw new InvalidClassException(localDesc.name,
04-01-2006