0

serialVersionUID seems to me to have a very loose specification. Any body developing a class with serializable interface can burn his hands with InvalidClassException. Also, i saw a fellow dev using int as a datatype rather than long.

So, my question why the Java designers and developers did not do something more concrete like whenever we implement serializable we have to implement a method setting serialVersionUID like the hashcode method.

So, what am i missing ? Does not seem like a double edged sword to me.

Update 1:

My bad i gave a wrong example comparing a class level thing with a instance level thing.I have seen many production issues across different companies because of this. But my general idea was cant it be made more strict by compiler in any way.

10
  • 1
    I used to get loads of serialVersionUID warnings when I wasn't trying to use serialization at all - I just happened to be extending some other serializable class. I had no reason to deal with serialVersionUID and would not have appreciated an extra requirement foisted upon me. Commented Aug 15, 2017 at 13:29
  • 2
    hashCode() is an instance method. All objects have their own hashCode. serialVersionUID is bound to the class, not to the instances of the class. Commented Aug 15, 2017 at 13:29
  • What do you mean "is not enforced by Java"? I agree, its not the best system really. Given everything we have available now, annotations are probably appropriate, but we didn't have those way back when. Commented Aug 15, 2017 at 13:33
  • Also note that the description of most Serializable class (EG Swing classes) have the following paragraph: " Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeans™ has been added to the java.beans package. Please see XMLEncoder. " Commented Aug 15, 2017 at 13:46
  • @GhostCat I disagree. Sure, the ID must be in the serialized bytes. But whether Java could call a static method rather than introspecting a static field to get that value. Of course, that would provide an additional way of shooting yourself in the foot: not returning always the same value from the method. Commented Aug 15, 2017 at 13:48

3 Answers 3

6

Keep in mind the requirements:

  • the bytes making up the ID must be present within the stream of bytes representing a serialized object
  • unless you invent something "on top", the only way to get there is by using a field
  • the ID must be identical for all objects of a class, thus the source of the ID should be static

Now step back:

  • there is no polymorphism for static methods
  • in that sense, it doesn't make a difference if you use a static field or call a static method to acquire the ID bytes when serializing an object
  • but you are going to write those bytes into the stream anyway

Conclusion: using a static field addresses all the above points . When you would be using a method - you still have to create that field. Let that sink in: when using a method, the implementation must call the method, write that as field into the byte stream - and when reading the byte stream, that number needs to be consumed - as it can't be mapped to a "real" field in the class. Compare that to: there is a static field that gets written into the byte stream and read from there.

So - from a technical point of view, the natural way to integrate such in ID somehow is by asking for a static field on the class.

Of course you could have invented something else. Modern day java might have used annotations. But such usage of annotations wasn't around when Java was invented (and this kind of serialization is in Java since day 1). And then: modern day java doesn't use "byte stream" oriented serialization in the first place.

Or as the answer from Stephen suggest - you could compute that ID based on the current content of the class. But again: this technology was invented 20 years ago. Back then, computing the id might have cost you 1, 5, 10 seconds. Compare that to the efforts of reading a static field.

Sign up to request clarification or add additional context in comments.

Comments

4

So, my question why the Java designers and developers did not do something more concrete like whenever we implement serializable we have to implement a method setting serialVersionUID like the hashcode method.

If I understand you correctly, you are saying that there should be a method to calculate the serialVersion. I can see problems with this:

  1. How would an application program calculate a decent serial version? Note that it must be calculated from type information ... not the values of fields.

  2. Calculating a serial version at run time (repeatedly) would be expensive.

  3. If we have lazy programmers who don't use the "serialver" tool to calculate a proper version number, the same lazy programmers are likely to implement this (hypothetical) method to return a bogus number ... and we are back where we started.

  4. There are use-cases where NOT changing the serial version ID is intentional.

No. The real solution to the problem of lazy programmers is code reviews.

Or ... maybe ... tooling to either regenerate the serialVersion constants, or flag them as suspicious.

Note that tools can't pick all of the cases where there is going to be a problem. However, neither can a code-reviewer. And code-reviewers get tired, have to be paid, etc.

(Finally, it might be a good idea if certain IDE's didn't offer setting the constant to -1 as a quick-fix ...)


But my general idea was cant it be made more strict by compiler in any way.

It is not a compiler thing. It is a runtime behavior of a specific set of library classes. The classes use Unsafe ... but the compiler is not aware of the significance of the serialVersionID variable.

3 Comments

How would such detection code differentiate between "field has be renamed" and "field has been deleted, and another one has been added"?
I don't think you can solve that. However, you can at least detect cases where the serialVersion definitely has to change because the representation types are clearly different.
(And "laziness" is often an incorrect characterization / explanation for abuse of serialVersionNo constants.)
2

Why the Java designers and developers did not [make us] have to implement a method setting serialVersionUID

The serialVersionUID is data related to the class. It's not data related to a single instance of the class.

If we had an interface such as:

interface MySerializable { long getSerialVersionUID(); } 

then we could implement that like this:

class Foo implements MySerializable { private String myField; //... public long getSerialVersionUID() { if(myField.equals("hello")) { return 1L; } else { return 2L } } } 

This doesn't make sense. The version cannot depend on the instance.

Now that we have annotations, a good solution in my eyes would be to write a @Serializable annotation. I prefer this because anything related to serialization is really just metadata. Adding an additional field completely unrelated to the class's behaviour just muddies the water.

@Serializable(ID = "1") class Foo { //... } 

Of course, annotations are a more recent addition so this wasn't an option when serialVersionUID was devised.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.