Hi all,
I would like to propose the following new rule.
Rule description & motivation
Providing a serialVersionUID
field in Serializable
classes is recommended, but blindly following that recommendation can be harmful.
First, there are applications that do not use serialization for long-term persistent storage, but only for short-term in-memory caching. Also, some classes like exceptions have to implement Serializable
.
In these situations, backwards compatibility or interoperability with code compiled by other compilers is not a goal. However, requiring an explicit serialVersionUID
makes it quite likely that developers forget to update it when they should. When this happens, incompatible versions of the class will be deserialized without any warning at runtime, leading to bugs later on that are hard to pinpoint.
Not specifying a serialVersionUID
can be the safer approach for such applications: the compiler will automatically generate a version, and the serialization runtime will refuse to deserialize an instance if the versions do not match. This gives the developer a hint that e.g. something is wrong with the classpath or different versions of the application use the same cache server.
Impact to keep this code as it is
Specifying a serialVersionUID
field poses the risk that it is not updated when it should, which introduces bugs that can be hard to diagnose.
Notes
This rule is the opposite of S2057 (“Serializable” classes should have a version id). Teams may use either that rule or this one depending on their requirements and application architecture. A team may even go so far as using both rules in their quality profile - then, using SonarQube’s capability of path-based rules, they can add an include entry for the “should have a version id” rule that limits it to those parts of their application where it’s relevant, and exclude issues from the new “use auto-generated version id” rule there.
If this rule is accepted, I suggest adding links to the other rule in the description of both rules.
Furthermore, independently of this rule suggestion, the description of S2057 should be changed: currently, it starts with “A serialVersionUID
field is required”, but it should read “A serialVersionUID
field is strongly recommended” to align with the wording given in the Serializable documentation:
However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected
InvalidClassExceptions
during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value.
The first sentence makes it quite clear it’s a recommendation; the word “must” in the last sentence only applies to the goal of compiler compatibility.
Noncompliant Code
public class Foo implements Serializable {
private static final long serialVersionUID = 1;
}
public class SubsystemException extends RuntimeException {
private static final long serialVersionUID = 8582433437601788991L;
}
References
- Alexander Torstling’s answer to “What is a serialVersionUID and why should I use it?”
- Reinier Zwitserloot’s answer to “feature request: @Serialized” - see item 4
- Vojtech Ruzicka: Should I explicitly declare serialVersionUID?
Type
Code Smell
Tags
pitfall
Best regards