What is a serialVersionUID and why should I use it?
Solution 1
The docs for java.io.Serializable
are probably about as good an explanation as you'll get:
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 differentserialVersionUID
than that of the corresponding sender's class, then deserialization will result in anInvalidClassException
. A serializable class can declare its ownserialVersionUID
explicitly by declaring a field namedserialVersionUID
that must be static, final, and of typelong
:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a
serialVersionUID
, then the serialization runtime will calculate a defaultserialVersionUID
value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declareserialVersionUID
values, since the defaultserialVersionUID
computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpectedInvalidClassExceptions
during deserialization. Therefore, to guarantee a consistentserialVersionUID
value across different java compiler implementations, a serializable class must declare an explicitserialVersionUID
value. It is also strongly advised that explicitserialVersionUID
declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class —serialVersionUID
fields are not useful as inherited members.
Solution 2
If you're serializing just because you have to serialize for the implementation's sake (who cares if you serialize for an HTTPSession
, for instance...if it's stored or not, you probably don't care about de-serializing
a form object), then you can ignore this.
If you're actually using serialization, it only matters if you plan on storing and retrieving objects using serialization directly. The serialVersionUID
represents your class version, and you should increment it if the current version of your class is not backwards compatible with its previous version.
Most of the time, you will probably not use serialization directly. If this is the case, generate a default SerialVersionUID
by clicking the quick fix option and don't worry about it.
Solution 3
I can't pass up this opportunity to plug Josh Bloch's book Effective Java (2nd Edition). Chapter 10 is an indispensible resource on Java serialization.
Per Josh, the automatically-generated UID is generated based on a class name, implemented interfaces, and all public and protected members. Changing any of these in any way will change the serialVersionUID
. So you don't need to mess with them only if you are certain that no more than one version of the class will ever be serialized (either across processes or retrieved from storage at a later time).
If you ignore them for now, and find later that you need to change the class in some way but maintain compatibility w/ old version of the class, you can use the JDK tool serialver to generate the serialVersionUID
on the old class, and explicitly set that on the new class. (Depending on your changes you may need to also implement custom serialization by adding writeObject
and readObject
methods - see Serializable
javadoc or aforementioned chapter 10.)
Solution 4
You can tell Eclipse to ignore these serialVersionUID warnings:
Window > Preferences > Java > Compiler > Errors / Warnings > Potential Programming Problems
In case you didn't know, there are a lot of other warnings you can enable in this section (or even have some reported as errors), many are very useful:
- Potential Programming Problems: Possible accidental boolean assignment
- Potential Programming Problems: Null pointer access
- Unnecessary code: Local variable is never read
- Unnecessary code: Redundant null check
- Unnecessary code: Unnecessary cast or 'instanceof'
and many more.
Solution 5
serialVersionUID
facilitates versioning of serialized data. Its value is stored with the data when serializing. When de-serializing, the same version is checked to see how the serialized data matches the current code.
If you want to version your data, you normally start with a serialVersionUID
of 0, and bump it with every structural change to your class which alters the serialized data (adding or removing non-transient fields).
The built-in de-serialization mechanism (in.defaultReadObject()
) will refuse to de-serialize from old versions of the data. But if you want to you can define your own readObject()-function which can read back old data. This custom code can then check the serialVersionUID
in order to know which version the data is in and decide how to de-serialize it. This versioning technique is useful if you store serialized data which survives several versions of your code.
But storing serialized data for such a long time span is not very common. It is far more common to use the serialization mechanism to temporarily write data to for instance a cache or send it over the network to another program with the same version of the relevant parts of the codebase.
In this case you are not interested in maintaining backwards compatibility. You are only concerned with making sure that the code bases which are communicating indeed have the same versions of relevant classes. In order to facilitate such a check, you must maintain the serialVersionUID
just like before and not forget to update it when making changes to your classes.
If you do forget to update the field, you might end up with two different versions of a class with different structure but with the same serialVersionUID
. If this happens, the default mechanism (in.defaultReadObject()
) will not detect any difference, and try to de-serialize incompatible data. Now you might end up with a cryptic runtime error or silent failure (null fields). These types of errors might be hard to find.
So to help this usecase, the Java platform offers you a choice of not setting the serialVersionUID
manually. Instead, a hash of the class structure will be generated at compile-time and used as id. This mechanism will make sure that you never have different class structures with the same id, and so you will not get these hard-to-trace runtime serialization failures mentioned above.
But there is a backside to the auto-generated id strategy. Namely that the generated ids for the same class might differ between compilers (as mentioned by Jon Skeet above). So if you communicate serialized data between code compiled with different compilers, it is recommended to maintain the ids manually anyway.
And if you are backwards-compatible with your data like in the first use case mentioned, you also probably want to maintain the id yourself. This in order to get readable ids and have greater control over when and how they change.
ashokgelal
Updated on August 06, 2021Comments
-
ashokgelal almost 3 years
Eclipse issues warnings when a
serialVersionUID
is missing.The serializable class Foo does not declare a static final serialVersionUID field of type long
What is
serialVersionUID
and why is it important? Please show an example where missingserialVersionUID
will cause a problem.-
ceyun over 4 yearsFind a good practise about serialversionUID; dzone.com/articles/what-is-serialversionuid
-
-
John Gardner over 15 yearsupvote but only because the original poster doesn't appear to be serializing anything. If the poster said "i'm serializing this thing and ..." then you'd get a vote down instead :P
-
brady over 15 yearsIf you're not going to serialize the objects, why are they Serializable?
-
user2918201 over 15 yearsSo, what you are saying essentially is that if a user did not understand all the above material, said user aught not bother worrying about serialization? I believe you answered the "how?" rather than explaining the "why?". I, for one, do not understand why I aught bother with SerializableVersionUID.
-
user2918201 over 15 yearsSo one might bother with SerializableVersionUID if one were concerned about compatibility w/ old versions of a class?
-
user2918201 over 15 years@Gardner -> agreed! But the questioner also wants to know why he might not want to be warned.
-
MetroidFan2002 about 15 years@erickson - the parent class may be serializable, say, ArrayList, but you want your own object (say, a modified array list) to use it as a base but are never going to serialize the Collection that you create.
-
Paŭlo Ebermann about 13 yearsIf you set the serialVersionUID always to the same value the generator would produce, you don't really need it at all. After all, its raison d'être is to stay same after changes, when the class is still compatible.
-
Tom Anderson about 13 yearsI'd say that if you're not using serialization for permanent storage, you should use @SuppressWarnings rather than adding a value. It clutters the class less, and it preserves the abiity of the serialVersionUID mechanism to protect you from incompatible changes.
-
MetroidFan2002 about 13 yearsI don't see how adding one line (@SuppressWarnings annotation) as opposed to another line (serializable id) "clutters the class less". And if you're not using serialization for permanent storage, why wouldn't you just use "1"? You would not care about the autogenerated ID in that case anyways.
-
Andrew almost 13 yearsThe reason is so that different compilers come up with the same value for the same class. As explained in the javadocs (also answered above), the generated version is brittle and can vary even when the class is properly deserializable. As long as you run this test on the same compiler each time, it should be safe. god help you if you upgrade the jdk and a new rule comes out, even though you code didn't change.
-
piepera over 12 yearsI think you're right that composition over inhneritance makes more sense, particularly when you're discussing classes such as ArrayList. However, many frameworks require people to extend from abstract superclasses which are serializable (such as Struts 1.2's ActionForm class, or Saxon's ExtensionFunctionDefinition) in which case this solution is infeasible. I think you're right, it would be nice if the warning were ignored in certain cases (like if you were extending from an abstract serializable class)
-
AbdullahC over 12 years@MetroidFan2002: I think @TomAnderson's point of
serialVersionUID
protecting you from incompatible changes is valid. Using@SuppressWarnings
documents the intent better if you don't wish to use the class for permanent storage. -
Chander Shivdasani over 12 yearsYup, in case if the newer version changes any public member to protected, the default SerializableVersionUID will be different and will raise an InvalidClassExceptions.
-
M_M over 11 yearsSurely if you add a class as a member, rather than inheriting from it, you would have to write a wrapper method for EVERY method of the member class that you wished to use, which would make it unfeasible in a large number of situations... unless java has a function similar to perl's
__AUTOLOAD
, which I don't know about. -
Paŭlo Ebermann over 11 years@M_M: When you would delegate lots of methods to your wrapped object, of course it would not be appropriate to use delegation. But I suppose that this case is a sign of a design mistake - the users of your class (e.g. "MainGui") shouldn't need to call lots of methods of the wrapped object (e.g. JFrame).
-
user207421 over 11 years"You should increment it if the current version of your class is not backwards compatible with its previous version:" You should first explore the extensive object versioning support of Serialization, (a) to ensure that the class really is now serialization-incompatible way, which per the specification is quite difficult to achieve; (b) to try a scheme such as custom read/writeObject() methods, readResolve/writeReplace() methods, serializableFields declarations, etc, to make sure that the stream remains compatible. Changing the actual
serialVersionUID
is a last resort, a counsel of despair. -
Achow about 11 yearsclass Name, implemented interfaces, all public and protected methods,ALL instance variables.
-
user207421 over 10 yearsAdding or removing non-transient fields doesn't make the class serialization-incompatible. There is therefore no reason to 'bump it' on such changes.
-
user207421 over 10 yearsIt isn't mentioned anywhere in the Java Language Specification. It's mentioned in the Object Versioning Specification.
-
user207421 over 10 yearsIt's not required to match what
serialver
would produce. -1 -
Alexander Torstling over 10 years@EJP: Huh? Adding data definitely changes the serialization data in my world.
-
user207421 almost 10 years@AlexanderTorstling Read what I wrote. I didn't say it doesn't 'change the serialization data'. I said it 'doesn't make the class serialization-incompatible'. It isn't the same thing. You need to read the Versioning chapter of the Object Serialization Specification.
-
user207421 almost 10 yearsThe algorithm doesn't vary, but it is slightly under-specified.
-
user207421 almost 10 yearsIt doesn't include HttpServlet in containers where they can be swapped out, or Exception in RMI for example.
-
Alexander Torstling almost 10 years@EJP: I realize that adding a non-transient field doesn't necessarily mean that you make the class serialization-incompatible, but it is a structural change which alters the serialized data and you usually want to bump the version when doing so unless you handle backwards compatibility, which I also explained later in the post. What is your point exactly?
-
JohnMerlino almost 10 yearsAnd why does Eclipse say I need "private static final long serialVersionUID = 1L;" when I extend the Exception class?
-
Jon Skeet almost 10 years@JohnMerlino: Well I wouldn't expect it to say you need one - but it may be suggesting one in order to help you serialize exceptions correctly. If you're not going to serialize them, you really don't need the constant.
-
Kranthi Sama almost 10 years@Vinothbabu but serialVersionUID is static so static variables cannot be serialized. then how come jvm will check version, without knowing what is the version of the deserializing object
-
Kirby almost 10 yearsThe one thing not mentioned in this answer is that you may cause unintended consequences by blindly including
serialVersionUID
without knowing why. Tom Anderson's comment on MetroidFan2002's answer addresses this: "I'd say that if you're not using serialization for permanent storage, you should use @SuppressWarnings rather than adding a value. It clutters the class less, and it preserves the ability of the serialVersionUID mechanism to protect you from incompatible changes." -
Ashutosh Jindal almost 10 yearsIt is worth noting that Joshua Bloch advices that for every Serializable class it's worth specifying the serial version uid. Quote from chapter 11: Regardless of what serialized form you choose, declare an explicit serial version UID in every serializable class you write. This eliminates the serial version UID as a potential source of incompatibility (Item 74). There is also a small performance benefit. If no serial version UID is provided, an expensive computation is required to generate one at runtime.
-
zpon over 9 years@JohnMerlino, to answer the why part of you question: Exception implements Serializable and eclipse warns that you have not set an serialVersionUID, which would be a good idea (if you wan't to serialize the class) to avoid the problems that JonSkeet's post outlines.
-
Basil Bourque over 9 yearsHere is the link to the Java 8 Object Versioning Specification.
-
WVrock over 9 yearsWhat I don't like about delegation is the need to hold a reference to the delegate. And every reference means more memory. Correct me if I'm wrong. If I need a CustomizedArrayList of 100 objects then this wouldn't matter much but if I need hundreds of CustomizdeArrayLists of a few objects then memory usage increases significantly.
-
smwikipedia over 9 years@JonSkeet So does it mean that besides having an identical class definition, I have to use exactly the same version number? How could I know that if I don't have a peek of the source code of the serialized class?
-
Jon Skeet over 9 years@smwikipedia: To deserialize data? Yes. It would be odd to deserialize data for a class you didn't have the source to though. Binary serialization shouldn't (IMO) be used as a general purpose public protocol.
-
overexchange over 9 years@EJP increment of serialVersionUID comes into picture when initial author of the class has introduced explicitly.I would say, jvm generated serial id, should be fine. this is the best answer that i saw on serialisation.
-
user207421 about 9 yearsMy point remains exactly what I said. Adding or removing non-transient fields doesn't make the class Serialization-incompatible. You therefore don't need to bump the serialVersionUID every time you do so.
-
user207421 about 9 years@overexchange What does 'has introduced explicitly' mean?
-
overexchange about 9 yearsI mean declared explicitly
-
user207421 almost 9 years
serialVersionUID
is not a 'unique identifier for each class'. The fully-qualified class name is that. It is a version indicator. -
amertkara almost 9 years@Ziggy If " .. 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." doesn't answer Why then I am afraid, I will have to ask you to define Why :D
-
Gaurav Jeswani over 8 years@JonSkeet You have mentioned in your answer "since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members." could you please explain this? Because as I know if the parent class is serialized the child is also serialized by default, so do we need to declare SerialVersionUID for child as well?
-
Jon Skeet over 8 years@proudandhonour: Yes, you should do so.
-
Gaurav Jeswani over 8 years@JonSkeet If I make it protected then what? Won't it inherited in child class?
-
Jon Skeet over 8 years@proudandhonour: I don't know exactly what happens in those cases, but why not just declare it separately in each class, as the documentation implies?
-
JimLohse over 8 yearsJust my two cents this is an issue in Spark and other parallelization APIs that depend on serializing Java classes across a cluster.
-
Ignazio about 8 yearsGives me an idea: always regenerate the serial version uid with a tool like this, never by hand, before making a release - that way, you avoid forgetting to make a change to a class whose serial version uid should have changed because of an actual incompatible change. Keeping track of that manually is very hard.
-
Asif Mushtaq almost 8 years@JonSkeet who generates default UID? JVM or Compiler/JDK?
-
Jon Skeet almost 8 years@UnKnown: The serialization runtime - it's at execution time.
-
Phil about 7 yearsThrowable is serializable, and only Throwable is throwable, so it's not possible to define an exception that isn't serializable. Delegation isn't possible.
-
cinqS about 7 yearsThe questioner obviously cares about why there should be an UID. So simply telling him to ignore the warn should be downvoted.
-
Paŭlo Ebermann about 7 years@Phil I think this is by design – even if you don't want to serialize your exception class, someone else might want to serialize an exception thrown by you. (Of course, one could argue that most exception classes should be fine with the auto-generated serialVersionUID and not need a fixed one.)
-
user1050755 almost 7 yearsSo, if I understand it correctly, manually specifying the uid is unsafer than letting the runtime generate it. Because sooner or later someone will forget to update it....
-
Jon Skeet almost 7 years@user1050755: There are pros and cons each way, basically.
-
user1050755 almost 7 yearsI can't see any cons against letting the runtime use the class "signature". Seems to be the perfect solution to me.
-
Jon Skeet almost 7 years@user1050755: So you're happy that changing your compiler, even if it wouldn't change any of the details of the fields themselves, could make any stored data unreadable? Or adding a public static method, which really shouldn't change serialization details? Having been bitten by exactly this sort of thing before, it's a very definite "con". Now it could be that if the algorithm had been designed better, it would be okay - but with the way it is designed, it's bad news.
-
Rogue almost 7 years@WVrock Well, that wouldn't be any different if you had numerous
ArrayList
instances either. An instance of your wrapper class is a size on the order of bytes + the size of the arraylist, whereas through inheritence you would be initializing the same amount but under 1 class definition. References are light, the underlying objects are heavy. -
abbas over 6 yearsAnd one should assign a random long number, not 1L, to every UID.
-
user207421 over 6 years@abbas 'One should' do that why? Please explain what difference it makes.
-
user207421 over 6 yearsEach time the class of an object is serialized the
serialVersionUID
is transmitted. It isn't sent with every object. -
user207421 over 6 years@overexchange You mean 'declared' what 'explicitly'?
-
overexchange over 6 years@EJP Declared serialVersionUID explicitly.
-
abbas over 6 yearsAs the name says, it represents the version of the class that was used to serialize the object. If you assign it the same number every time, you won't be able to find the right class to de-serialize it. So whenever you make a change in the class, it is better to change the version too.
-
Vadzim over 6 years@abbas, this intention doesn't clash with using incrementing natural numbers from
1
and so on. -
Bill K over 6 yearsIn general it's not required at all. @AndrewBacker's case would require two different compilers on the same .java file with both versions of the .class files communicating with each other--most of the time you just create the class and distribute it. If that's the case, then not having an SUID would work fine.
-
Vadzim over 6 years@BillK, I thought serialization check is bound to the pair of classname and serialVersionUID. So different numbering schemes of different classes and libraries can't interfere in any way. Or did you imply code-generating libraries?
-
john16384 over 6 yearsIf you're not using serialization (in like 99.9999% of the cases) just turn off this stupid default warning. No pointless meaningless random numbers in your code and no unnecessary SuppressWarnings. Jeez, every time I see code bases which "workaround" this warning I really wonder why they not simply turn off this warning (and perhaps activate a few that are more useful), instead of this zombie mentality to just "fix" the warning.
-
john16384 over 6 yearsPeople that truly use Serialization for purposes of storage / retrieval will generally set the
serialVersionUID
to 1. If a newer version of the class is incompatible, but still requires to be able to handle the old data, you increment the version number and add special code to deal with older formats. I cry every time I see aserialVersionUID
larger than 1 digit, either because it was a random number (useless) or because the class apparently needs to deal with more than 10 different versions. -
user207421 about 6 years@abbas
serialVersionUID
doesn't have anything to do with 'find[ing] the right version of the class'. -
user207421 about 6 yearsRubbish. It is adequate in the case where the class hasn't changed. You have zero evidence to support '99.9999%'.
-
android developer almost 6 yearsTip: If you've forgotten to add the
serialVersionUIDfield
, and you wish to change the class without affecting it, you can check what is its value on the unmodified and set it on this class after you've modified it, using this call (found from : stackoverflow.com/a/26822688/878126):long serialVersionUID = ObjectStreamClass.lookup(YourClass.class).getSerialVersionUID();
-
Alex78191 almost 6 years@TomAnderson No warning are shown in IDEA by default.
-
Darrell Teague almost 6 yearsMuch of this revolves around serialization and why it should probably NOT be used as an over-the-wire protocol or persistently stored and retrieved via deserialization. It effectively creates an implementation of "equals" at the class-level and without any reasonable method across JVMs and countless apps/classes created by any number of developers to make this consistent/unique for a given class... creates a nuanced bug immediately for junior developers should they persist the class as serialized data and then let the compiler try to sort out the version of a class during deserialization.
-
user207421 almost 5 years@overexchangeI agree entirely with @JBNizet's answer, but there is nothing there about incrementing the
serialVersionUID
. You should either leave it alone or change it to the newly computed value as reported by theserialver
tool, having first thoroughly explored the alternatives I mentioned, and having even prior to that determined definitely that it really needs to change, which it usually doesn't. There is nothing to be gained by deliberately introducing incompatibilites, especially when gratuitous. -
bpoiss almost 5 yearsSo what will happen if I update my class but do not update the
serialVersionUIDfield
? -
Jon Skeet almost 5 years@bpoiss: Then it will try to deserialize old data with the new class, and will either cause errors or effectively corrupt data, depending on the exact change.
-
AnthonyJClink over 4 years... the algorithm doesn't vary, but it is slightly under-specified... meaning any jvm may vary..... @user207421
-
Volksman about 4 yearsThe thing I always found crazy was that the algorithm to derive serialVersionUID when none is explicitly declared is based on package, name, attributes but ALSO methods... methods are not serialized and adding/removing methods makes no difference to the serialized form of the object so why produce a different serialVersionUID when a method is added/deleted/changed"?
-
Victor almost 4 yearsCorrect me if I'm wrong - the local class is the one that you are currently having/using in the classpath and the stream one is the one used by another party (eg. a server that is returning you an answer and has serialized the response). You can encounter this situation when you are communicating with a server that has updated its 3rd party libs, but you (the client) did not yer done this.
-
Dorian Gray over 3 yearsThe problem is not that it isn't "good", but it isn't guaranteed to be consistent over different versions.
-
Ben over 3 yearsSeems relevant. A link to a couple approaches to generate the serial version UID using IDEs: mkyong.com/java/how-to-generate-serialversionuid
-
The incredible Jan about 3 yearsYou will always run into problems without serialVersionUID if you have to change a class that has to stay backward compatible with it's serialization.
-
Mugeesh Husain over 2 yearsI am getting InvalidClassException because i haven't define serialVersionUID on the first place, how to fix this issue now ?
-
user207421 about 2 years@MugeeshHusain No you aren't. Omitting it doesn't cause that exception. Changing the class subsequently does. All you need to do now is to add a
serialVersionUID
member whose value is whatever the exception said the 'stream value' was.