228

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?

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
IAdapter
  • 62,595
  • 73
  • 179
  • 242
  • 51
    How is that exact duplicate? I dont ask why generate it at all, but why generate long serialVersionUID. – IAdapter May 20 '09 at 14:43
  • 14
    When Jon Skeet uses serialVersionUID, he uses 0L: http://stackoverflow.com/questions/605828/does-it-matter-what-i-choose-for-serialversionuid-when-extending-serializable-cla/605832#605832 ;) – Hanno Fietz Oct 05 '09 at 13:19
  • 10
    @HannoFietz: The exact sentence is: "For simplicity I'd suggest **starting** with 0 and **increasing it by 1** each time you need to." So, it sounds like he uses `0L` only initially. – O. R. Mapper Dec 20 '12 at 10:03
  • 7
    @O.R.Mapper: Are you implying that Jon Skeet ever needs to go back and update code he has written? Even to the point of structural incompatibility. Gasp! Heresy! – Thilo Oct 28 '15 at 05:21

10 Answers10

97

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.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
78

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:

Balder
  • 8,623
  • 4
  • 39
  • 61
coobird
  • 159,216
  • 35
  • 211
  • 226
  • 56
    The idea behind using 1L is so that you increment it every time you change the class properties or methods. – Powerlord May 20 '09 at 14:47
  • 39
    There is no runtime performance impact of allowing the serialversionUID to be generated automatically - it's generated at compile time by javac...if you decompile the class's bytecode, you'll actually see the variable statically in the bytecode. – Jared May 20 '09 at 18:58
  • 12
    One more note - by managing the number explicitly you get to decide when you consider versions of a class "compatible", rather than requiring the class definition to be exactly the same. – Scott Stanchfield May 21 '09 at 13:56
  • 23
    @ Jared According to Item 75 in Josh Bloch's Effective Java: 2nd Edition: "declare an explicit serial version UID in every serializable class you write.... If no serial version UID is provided, an expensive computation is required to generate one at runtime." – Colin K Dec 17 '09 at 00:54
  • 1
    I thought it was to distinguish ANY serialized object of any class lol. In which case, it's quite non-sense to manually type it. But now, I understand better. Versions make more sense. Thanks. – Adrien Gorrell May 30 '13 at 08:58
  • 14
    @coobird This seems to be the main reason why the default serialVersionUID is not recommended `Note - 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 serialVersionUID conflicts during deserialization, causing deserialization to fail. ` The above comment was taken from Java Object Serialization Specification version 6.0 – user624558 Sep 24 '14 at 01:38
22

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.

Robin
  • 24,062
  • 5
  • 49
  • 58
  • 3
    OK but the same will be If i have always 1L. Everything will be compatible even if I will made any change. – grep Jun 22 '15 at 14:40
  • @grep try renaming a field and then see what happens. – Hakanai Aug 17 '15 at 02:48
  • 1
    @grep the point is that if you have a class that omitted the serialVersionUID before, it would've gotten the generated one automatically. So now, you want to start setting it explicitly, setting it to 1L would make it incompatible to the existing class, whereas using the generated value keeps it compatible. – marc82ch Apr 14 '16 at 06:05
15

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.
Gray
  • 115,027
  • 24
  • 293
  • 354
Pankaj Kumar
  • 81,967
  • 29
  • 167
  • 186
  • 2
    As a matter of fact, deserializing old versions of the class should indeed fail because they are not the same anymore. You suggest generating serialVersionUID by oneself to prevent (de)serialization failures when the class signature changes. Although your suggestion is appropriate, your explanation of its purpose is simply wrong and misleading. It would be wise to modify your answer. – mostruash Feb 22 '13 at 12:15
  • 1
    It can be both good and bad - if all you've changed is some method body (eg, added null-check) and you've not changed / added any field then you don't really want the serialVersionUID to be different. – Kamil Bęben Mar 29 '21 at 18:01
15

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.

reevesy
  • 3,452
  • 1
  • 26
  • 23
David Schmitt
  • 58,259
  • 26
  • 121
  • 165
8

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.

joeforker
  • 40,459
  • 37
  • 151
  • 246
  • You meant ==> 1. If you want different changes of classes to be compatible use the generated one. 2. If you want different versions of classes to be incompatible use default one, and be prudent in incrementing. Did I understand it correctly ? – JavaDeveloper Jan 01 '14 at 20:57
3

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. :)

SomeGuy
  • 63
  • 2
  • If a "system" touches the class, i.e. changes the class in a way that the serialization becomes incompatible then the question is if that system will also change the serialVersionUID. I don't think that the odds are smaller that it will remember to change it when it is long. I think rather the opposite is true, if the number are easier to remember changes are higher that I notice that I accidentally didn't change it. – Reto Gmür Dec 10 '13 at 15:34
  • 3
    This is false! When you generate serialVersionUID, and declare that value in your source code, rather than 1L or nothing you are actually saying: I want a possibly undetected collision in the future with undefined effects, and I don't want java or any humans to prevent this. Java is paranoid, but obedient. Humans usually don't mess with big numbers. This way, when the class changes, java can still de-serialize old incompatible versions of it. MwoaHaHa... ;) – Superole Dec 17 '14 at 14:27
  • The auto-generated numbers are generated only once; but they have to be changed every time the class implementation is changed in an incompatible way, too. Starting with 0L or 1L makes it more likely humans will see and update the number. And there is an additional risk the big "magic number" is left untouched on changes because people don't know what it is for, or what they are supposed to do with it. – foo Jun 01 '23 at 11:36
1

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.

Lucky
  • 16,787
  • 19
  • 117
  • 151
1

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.

James Drinkard
  • 15,342
  • 16
  • 114
  • 137
0

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

Pushpendra Kuntal
  • 6,118
  • 20
  • 69
  • 119
  • Can you edit your answer to flesh it out more? This seems like a comment here. THanks. – Gray Mar 23 '17 at 03:55