JDK 9 RFR of JDK-8035452: Fix serial lint warnings in core libs
Stuart Marks
stuart.marks at oracle.com
Tue Feb 25 06:53:41 UTC 2014
On 2/24/14 8:22 PM, Joe Darcy wrote:
> On 02/20/2014 12:49 PM, Paul Benedict wrote:
>> Joe, I find it interesting that you suppressed the serial warning on an
>> abstract class. I'd like to know more about that. Is this a universal rule?
>> Are serial uids not important for abstract classes?
>
> I wouldn't generalize that way from this example.
>
> The serial hash of NavigableSubMap has differed in different JDK releases,
> but its subclasses do define serialVersionUID fields. I assume the set of
> non-transient fields in NavigableSubMap has stayed unchanged, but I haven't
> verified that.
>
> If I hadn't found the change in the hash value, I would have added the
> serialVersionUID to NavigableSubMap too.
And in his reply to Paul, Joe said:
> From what I was able to discern by reading the serialization specification
> [1], If a class does *not* declare a serialVersionUID, the serialVersionUID
> of its superclass is *not* included in the serialver hash computation of the
> child class. However, my understanding is that changes to the fields stored
> in superclass and changes to the semantics of its readObject / writeObjects
> methods could affect the serialization of the child class.
I think we need to take a closer look at these issues.
I believe that abstract, serializable superclasses *do* need to have a
serialVersionUID defined. The reason is that when a subclass is serialized, its
superclass descriptor (an ObjectStreamClass) is also serialized. Upon
deserialization, the descriptor's svuid is matched against the svuid of the
class loaded at runtime, and if there is a mismatch, InvalidClassException ensues.
While the svuid of an abstract superclass isn't included in the subclass' svuid
hash, the svuid of the superclass does affect serial compatibility of subclasses
as described above. Thus, an apparently innocuous change to the superclass might
prevent serial compatibility of its subclasses, no matter how carefully the
subclasses are programmed.
If the NavigableSubMap class has changed svuid values over several releases,
well, unfortunately we may have a compatibility problem already in the field.
We'd need to choose which release to be compatible with. Since 8 isn't quite out
yet, we might be able to change an early 8-update and 9 to be compatibile with
the latest 7-update.
Note that the svuid of a class does not relate solely to the fields that are
serialized. It's an attempt at a version hash of the *implementation* of a
class, not a version of the serial protocol. Even changes to a class that don't
affect the serialized output stream can affect the svuid. For example, renaming
a package-private method will affect the svuid. See section 4.6 of the
serialization spec.
While we're at it (sorry...) in the diffs for your other serial warnings patch
JDK-8035453, there are several lines where the serial warning is suppressed like so:
+ at SuppressWarnings("serial") // JDK implementation class
As you know, serialization can expose the private fields of a class, making them
public in a sense. Serialization can also expose what are internal,
implementation classes, if these classes are part of a serializable object graph
that is exposed to applications. I don't know about the specific situation with
the DOM classes, but even if a serializable class is internal, we might need to
be concerned about serialization compatibility.
Finally, EnumSet doesn't need a serial version UID. It's serialized using a
proxy class, so EnumSet never appears in a serialized byte stream. (Note, its
readObject throws an exception unconditionally.) So it's probably safe to
suppress its serialization warning.
s'marks
More information about the core-libs-dev
mailing list