24

There are 3 ways to define the serialVersionUID :

1. private static final long serialVersionUID = 1L; (Default)
2. private static final long serialVersionUID = -8940196742313994740L; (Generated)
3. Don't define serialVersionUID and let the JVM define it at runtime. @Lance Java

But I don't understand the first way!

I have seen it already, that somebody defines "serialVersionUID=1L" for all java-classes in source code.

What is the meaning? Is that useful?

If all classes have the same serialVersionUID 1L, is there no problem?

Ying Style
  • 752
  • 2
  • 7
  • 25
  • 3
    The actual value does not matter, what matters is, that you change it, when making incompatible changes to the class. Have look here: http://stackoverflow.com/questions/3284979/java-when-do-i-have-to-change-the-serialversionuid – qqilihq Feb 18 '14 at 10:30
  • It typically doesn't matter what serialVersionUID is assigned to. – Rhys Feb 18 '14 at 10:33
  • 1
    @Rhys This statement is too general for sure. – qqilihq Feb 18 '14 at 10:36
  • Great question. Any other language use such a feature? – Leo Feb 18 '14 at 10:39
  • 1
    Note, there's also a third option. Don't define `serialVersionUID` and let the JVM define it at runtime. – lance-java Feb 18 '14 at 10:46

8 Answers8

19

What is the meaning? Is that useful?

Yes. The point of serialVersionUID is to give the programmer control over which versions of a class are considered incompatible in regard to serialization. As long as the serialVersionUID stays the same, the serialization mechanism will make a best effort to translate serialized instances, which may not be what you want. If you make a semantic change that renders older versions incompatible, you can change the serialVersionUID to make deserializing older instances fail.

If all classes have the same serialVersionUID 1L, is there no problem?

No - the serialVersionUID is per class.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
8

This is explain here:

The serialVersionUID is a universal version identifier for a Serializable class. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If no match is found, then an InvalidClassException is thrown.


From the javadoc:

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:


Useful Links

  1. java.io.Serializable
  2. Why should I bother about serialVersionUID? (StackOverflow)
  3. serialVersionUID in Java Serialization
Community
  • 1
  • 1
ravibagul91
  • 20,072
  • 5
  • 36
  • 59
7

The JVM will throw a InvalidClassException if the serialVersionUID of a serialized object does not match the serialVersionUID of the class it is being deserialized as.

The serialVersionUID of a class should change every time the class changes in an incompatible way. Normally this means every time you change the shape of a class (ie fields or methods change).

There are some cases where you don't want the serialVersionUID to change. For instance you might accept old versions of the object into your application. In this case, you can leave the serialVersionUID the same and new fields will come through as null.

lance-java
  • 25,497
  • 4
  • 59
  • 101
7

Yes, I've seen code that defined serialVersionUID like that too. I think it is a bad idea.

In this context there is only one "distinguished" value for the serialVersionUID field; i.e. zero ... 0L. Zero means "compute the version id at runtime by applying the standard algorithm" based on the actual class that you are serializing / deserializing. That means that whenever your code's effective serialization signature changes, the serialization / deserialization code will use a different version id. From a (big picture) type safety perspective, this is the safest thing to do, though it is also somewhat inefficient, and protentially more fragile.

What is the meaning?

The 1L has no special meaning. It is just a number that will match 1L as the "other" version id.

To my mind, you are better off either using 0L, or a version number that was (at some point) generated using the standard algorithm.

  • If you use 0L, then you get definite deserialization exceptions if classes change in ways that could be source of problems. If you need this, it is a good thing.

  • On the other hand you use a generated version id, you (the programmer) can make your own decision about when to regenerate the id. And when you do decide to regenerate, the id will only change if the class signature has changed. (If classes representation etc hasn't changed, the regenerated signature should be identical to the original one!) And when the id does change, you can think about whether to add custom methods ('readObject', etc) to deal with the incompatibility.

  • However, if you use 1L, you can't tell if the version id needs to change without checking your code history, and comparing the old / new versions of the classes ... back as far as you need to.

Is that useful?

It depends on what you consider "useful" to mean. If you think it is a good thing to hard wire the version id to "trust me, it is ok", then 1L is useful.


My recollection is that some versions of Eclipse offer 1L as one of the possible auto-corrections for a missing serialVersionUID field warning. That is probably where the examples you see have come from.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • isn't the contention that by specifying a number it's analogous to a version control commit? – Thufir Aug 18 '17 at 15:20
  • Whose contention? Not the OP's. Not mine. And it wouldn't be useful to change the number on each commit. If that is what you are implying ..... – Stephen C Aug 19 '17 at 01:28
5

Imagine you write a class with a serialVersionUID, instantiate it, then serialize it to a file (with ObjectOutputStream)

Then you modify the class.

Then, with the modified class, you deserialize (read in) the version you serialized before modification. Java will check the serialVersionUID of the current class and the serialized class, and if they don't match, the deserialization will fail. This is a deliberate fail-fast to prevent much more subtle (and harder to debug) errors occurring later on due to class version incompatibilities.

If you omit serialVersionUID then you disable the version checking. If you always set if to 1L, then the check will always pass (the value is always the same) so you are still vulnerable to subtle class version incompatibility problems.

NickJ
  • 9,380
  • 9
  • 51
  • 74
2

The value is used while serializing an object and de-serializing the object back into JVM.

Further, If your class changes and you don't want to support backward compatibility (i.e. able to de-serialize the object back which was serialized using your last version of class) you can change the version number to any other value.

However, to support the backward compatibility you need to keep the same version number as previously set value of serialVersionUID.

The best practice is to change the serialVersionUID, every time you have some incompatible changes to the class.

sakura
  • 2,249
  • 2
  • 26
  • 39
2

It's important to make clear the fact that having a class implement the Serializable interface makes ALL fields not declared transient part of the exported API of the class, whether or not those fields are declared private.

In other words, implementing Serializable:

  • breaks encapsulation. If the class has any chance to become a successful, long-lived class then you must support the serialized form ... forever.

  • can seriously impair your ability to evolve that class, precisely because it is a part of its exported API. The alternative is to break backward compatibility.

  • can create security problems for your class and its application. Deserialization represents a way for making Java objects without a constructor, so it's possible to violate a class's invariants by providing rogue byte streams to the deserialization facility.

The serialVerionUID should be thought of as a property of the serialized form. It is meant to convey to one JVM whether or not there a difference between the serialized form of a class instance that it is receiving and the serialized form of of that same class rendered (maybe) somewhere else.

You can see the potential problems that may occur if the serialized forms are different but the UIDs are the same. The receiving JVM will assume that the received serial form version between an old class and the new one are the same when they aren't and will dutifully go ahead and attempt to deserialize the byte stream.

TLDR: You shouldn't change the UID when you feel like it. You should change it when the serialized form of the class changes so that versions of software that use older versions of your class (with the different serialized form) will break instead of (possibly silently) doing the wrong thing. Not designing a good serialized form your classes will make it harder (even much harder) to provide backward compatibility for its clients. In the ideal case, the serialized form for a class persists throughout its entire evolution (and so its UID need never change).

scottb
  • 9,908
  • 3
  • 40
  • 56
1

You can assign any long value to serialVersionUID, but you have to change it every time you modify your class.

The second looks like a generated serialVersionUID, based on the features of the current class version.

Marco Bolis
  • 1,222
  • 2
  • 15
  • 31
  • Where does it say you have to change it every time you modify your class! – user207421 Feb 18 '14 at 10:37
  • I don't know where it says it, but trying to deserialize an object serialized with a different version of the class can lead to surprising behavior. Assigning a different `serialVersionUID` will outright cause an exception. No more nasty surprises... – Marco Bolis Feb 18 '14 at 10:43
  • 2
    It is not strictly necessary to change it every time, but if you do not, you'd need to determine if the new version of the class is still compatible with old serialized versions. Making such a determination is not a trivial task. Safer to change it every time. – NickJ Feb 18 '14 at 13:18