Why generate long serialVersionUID instead of a simple 1L?

JavaSerializationCode GenerationSerialversionuid

Java Problem Overview


When class implements Serializable in Eclipse, I have two options: add default serialVersionUID(1L) or generated serialVersionUID(3567653491060394677L). I think that first one is cooler, but many times I saw people using the second option. Is there any reason to generate long serialVersionUID?

Java Solutions


Solution 1 - Java

As far as I can tell, that would be only for compatibility with previous releases. This would only be useful if you neglected to use a serialVersionUID before, and then made a change that you know should be compatible but which causes serialization to break.

See the Java Serialization Spec for more details.

Solution 2 - Java

The purpose of the serialization version UID is to keep track of different versions of a class in order to perform valid serialization of objects.

The idea is to generate an ID that is unique to a certain version of an class, which is then changed when there are new details added to the class, such as a new field, which would affect the structure of the serialized object.

Always using the same ID, such as 1L means that in the future, if the class definition is changed which causes changes to the structure of the serialized object, there will be a good chance that problems arise when trying to deserialize an object.

If the ID is omitted, Java will actually calculate the ID for you based on fields of the object, but I believe it is an expensive process, so providing one manually will improve performance.

Here's are a couple of links to articles which discuss serialization and versioning of classes:

Solution 3 - Java

The main reason for the generated one would be to make it compatible with an existing version of the class that already has persisted copies.

Solution 4 - Java

The "long" default of the serialVersionUID is the default value as defined by the Java Serialization Specification, calculated from the default serialization behaviour.

So if you add the default version number, your class will (de-)serialize faster as long as nothing has structurally changed, but you'll have to take care that if you change the class (add/remove fields) you also update the serial number.

If you do not have to be compatible to existing bit streams, you can just put 1L there and increment the version as needed when something changes. That is, when the default serialisation version of the changed class would be different from the default version of the old class.

Solution 5 - Java

You absolutely should create a serialVersionUID every time you define a class that implements java.io.Serializable. If you don't, one will be created for you automatically, but this is bad. The auto-generated serialVersionUID is based on the method signatures of your class, so if you change your class in the future to add a method (for example), deserializing the "old" versions of the class will fail. Here's what can happen:

  1. Create the first version of your class, without defining the serialVersionUID.
  2. Serialize an instance of your class to a persistent store; a serialVersionUID is automatically generated for you.
  3. Modify your class to add a new method, and redeploy your application.
  4. Attempt to deserialize the instance that was serialized in step 2, but now it fails (when it should succeed), because it has a different auto-generated serialVersionUID.

Solution 6 - Java

If you don't specify a serialVersionUID then Java makes one on the fly. The generated serialVersionUID is that number. If you change something in your class that doesn't really make your class incompatible with previous serialized verisons but changes the hash, then you need to use the generated very-large-number serialVersionUID (or the "expected" number from the error message). Otherwise, if you are keeping track of everything yourself, 0, 1, 2... is better.

Solution 7 - Java

When you use serialVersionUID(1L) rather than generating serialVersionUID(3567653491060394677L) you are saying something.

You are saying that you are 100% confident that no system that will ever touch this class that has an incompatible serialized version of this class with a version number of 1.

If you can think of any excuse for it's serialized version history to be unknown, that might be hard to say with confidence. In it's lifetime, a successful class will be maintained by many people, live in many projects, and reside in many systems.

You can agonize over that. Or you can play the lottery hoping to lose. If you generate the version you have a tiny chance of things going wrong. If you assume "Hey I bet no one used 1 yet" your odds are larger than tiny. It's precisely because we all think 0 and 1 are cool that you have higher odds of hitting them.

When you generate serialVersionUID(3567653491060394677L) rather than use serialVersionUID(1L) you are saying something.

You are saying people may have either manually created or generated other version numbers over the history of this class and you don't care because Longs are freaking big numbers.

Either way unless you perfectly know the history of version numbers used when serializing the class in the entire universe of where it has or will ever exist, you're taking a chance. If you have the time to make 100% sure 1 is AOK, go for it. If that's to much work, go ahead and blindly generate the number. You're more likely to win the lottery than to have that go wrong. If it does, let me know and I'll buy you a beer.

With all this talk of playing the lottery I may have given you the impression that serialVersionUID is generated randomly. In fact as long as the range of numbers is evenly distributed over every possible value of a Long that would be fine. However, it's actually done this way:

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100

The only difference you get with that is you don't need a source of random. You're using the changes in class itself to change the result. But according to the pigeonhole principle there is still a chance it could go wrong and have a collision. It's just incredibly unlikely. So good luck getting a beer out of me.

However, even if the class will only ever live in one system and one code base, thinking that incrementing the number by hand gives you zero chance of collisions just means you don't understand humans. :)

Solution 8 - Java

Well, serialVersionUID is an exception to the rule that “static fields don’t get serialized”. ObjectOutputStream writes every time the value of serialVersionUID to the output stream. ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException. Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.

Solution 9 - Java

Because in many cases default id is not unique. so we create id for making unique concept.

Solution 10 - Java

To add to @David Schmitts answer, as a rule of thumb I would always use the default 1L out of convention. I've only had to go back and change some of them a few times, but I knew that when I made the change and updated the default number by one each time.

At my current company they require the auto-generated number so I use that for convention, but I prefer the default. My take is, if it's not a convention where you work, use the default, unless you think you will be constantly changing the structure of you serialized classes for some reason.

Solution 11 - Java

The purpose of the serialization version UID is to keep track of different versions of a class in order to perform valid serialization of objects.

The idea is to generate an ID that is unique to a certain version of an class, which is then changed when there are new details added to the class, such as a new field, which would affect the structure of the serialized object.

A Simple Explanation:

Are you serializing data?

Serialization is basically writing class data to a file/stream/etc. De-serialization is reading that data back to a class.

Do you intend to go into production?

If you are just testing something with unimportant/fake data, then don't worry about it (unless you are testing serialization directly).

Is this the first version?

If so, set serialVersionUID=1L.

Is this the second, third, etc. prod version?

Now you need to worry about serialVersionUID, and should look into it in depth.

Basically, if you don't update the version correctly when you update a class you need to write/read, you will get an error when you try to read old data.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIAdapterView Question on Stackoverflow
Solution 1 - JavaMichael MyersView Answer on Stackoverflow
Solution 2 - JavacoobirdView Answer on Stackoverflow
Solution 3 - JavaRobinView Answer on Stackoverflow
Solution 4 - JavaDavid SchmittView Answer on Stackoverflow
Solution 5 - JavaPankaj KumarView Answer on Stackoverflow
Solution 6 - JavajoeforkerView Answer on Stackoverflow
Solution 7 - JavaSomeGuyView Answer on Stackoverflow
Solution 8 - JavaLuckyView Answer on Stackoverflow
Solution 9 - JavaPushpendra KuntalView Answer on Stackoverflow
Solution 10 - JavaJames DrinkardView Answer on Stackoverflow
Solution 11 - JavaSaurabh VermaView Answer on Stackoverflow