The vast majority of examples of a Java serialVersionUID I have seen has a very long long value - see for example here where the given example is static final long serialVersionUID = 10275539472837495L or even the documentation which gives an example of static final long serialVersionUID = 42L
Is there any reason, though, that I can't call the first version of my class(es) static final long serialVersionUID = 1L the second 2L and so on? It compliles, serialises and deserialises fine but I was wondering if there were deeper reasons that made it not best practice.
From the Serializable Interface Docs:
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID 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 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 InvalidClassExceptions during deserialization.
When you see a serialVersionUID such as 10275539472837495L, it is most probable one that was generated by the serialization runtime.
So, why would you explicitly set the serialVersionUID to one generated by the runtime? Suppose you forgot to set the serialVersionUID to a specific value such as 1L, and you serialized a class. After a while, you make some changes to the class implementing the Serializable interface and all out of sudden, an InvalidClassException is thrown because the generated serialVersionUIDs do not match anymore. To fix this, you can explicitly set the serialVersionUID to that generated with the previous version. This is pretty much how one might end up with these long serialVersionUIDs.
To avoid this alltogether, it is recommended to explicitly declare serialVersionUID values, as stated in the docs.
Related
I just came across "WTF" sort of error: I updated one of my classe's methods and added one method too. After running my program, this is what popped our when program tried to open and unserialize recently saved data (before the methods changes):
java.io.InvalidClassException: cz.autoclient.settings.Settings; local class incompatible: stream classdesc serialVersionUID = 2404650814140543454, local class serialVersionUID = 4256355437298300223
According to what java documentation says about that, java methods are not being serialized. So why does the serialVersionUID take class methods in account too?
Since Java programmers seem to be so mad about using getters and setters literally everywhere, why is it not possible to create getter for serialVersionUID so that I can implement my own algorithm that only calculates the properties?
The serialVersionUID can be overriden, but only with static final long serialVersionUID value which would require me to remember to change it when I change class's properties.
Based on the documentation for java, they recommend to use custom serialVersionUID as much as possible, because the default algorithm will take class implementation details and the result is said to vary from JVM implementation to another.
The default algorithm used by Java to generate the serialVersionUID seems to be considering the non-private methods (step 7) as well. Which explains the exception if you were using the default serialVersionUID in your implementation.
EDIT:
As you suggested, it would be great if we can have our own implementation of a method to do this, rather than overriding the serialVersionUID as a static final long. But I guess they don't allow that because if it were allowed, wrong implementations of such a method could invalidate the whole purpose of the serialVersionUID.
The Oracle docs indicate that if you do not provide a serialVersionUID, the compiler will generate one for you.
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID 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 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 InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID 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. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
And according to the Java Object Serialization Specification section 5.1
Versioning raises some fundamental questions about the identity of a class, including what constitutes a compatible change. A compatible change is a change that does not affect the contract between the class and its callers.
What's happening here is that the compiler has decided the difference between the two versions of your code warrant a new serialVersionUID. If you feel that the state contained in an instance of Object(1) and Object(2) are interchangeable, you should manage this by setting the serialVersionUID manually and keeping it the same between those changes.
Yes, you will have to manually manage this, and change it when you make changes to the mechanisms which manage the internal state of the class.
As a note though, if the public methods have changed, you should consider if the original version of the class meets the same expectations as the new version. If you would like the data contained in the previously-serialized state to be loaded into a new version of the class, perhaps use a static constructor method to initialize the new version (new behavior) with the compatible, old state.
class A implements Serializable{
private static final long serialVersionUID = 5L;
...
}
and
class B implements Serializable{
private static final long serialVersionUID = 6L;
...
}
then it is necessary to give unique serialVersionUID to both classes.
So can I assign serialVersionUID = 5L for both classes?
I read following links
Why generate long serialVersionUID instead of a simple 1L?
What is a serialVersionUID and why should I use it?
Yes, you can. Serial versions of different classes are independent and do not interfere each other.
PS
Eclipse even proposes you to set serialVersionID by default value that is 1L.
serialVersionUID is needed to remember versions of the class. It should be same while serializing and deserializing. It is a good programming practice to provide this value rather than JVM assigning one(generally it is hash). It is not necessary for two classes to have unique values.
serialVersionUID can be anything.
But the best practice is to start with the lowest number (for example 0L) and update it whenever you make a change in class which affects serialization, for example, adding/updating/removing a field, in which case you should increase the version number from 0L to 1L and so on.
SerialVersionUUID is an identifier used by a compiler to serialize/deserialize an object. This id is a private member to the class.
Creating new uuid for every serializable is good to have control over the serialization/deserialization process but it need NOT be unique among different classes.
I have a class say Counter. I serialize Object of this class on JVM-1 in one machine & transfer the serialized Object as a network stream to another machine & deserialize there in JVM-2.
Will this Object get deserialized properly ?
Would there be any error/exception thrown in this case?
Assuming i have compiled the class on both JVMs.
I am assuming that there is no serial Version UID present in the classes
As long as you have the same code/jdk (though different jdks may work) running at both ends, serialization-deserialization would not be a problem.
if you have serialVersionUID in your class, serialize/deserialize will not be a problem, but if serialVersionUID is missing in your code, as you are compiling class with both JVM(I understand, .class file has same content but compiled with different JVMs) in that case, serialVersionUID is assigned by java, which won't be same, hence serialize/deserialize will not work.
So, add
private static final long serialVersionUID = -6903933977591709194L;
in case you haven't added, with any value, and compile as many times, rest assured, serialize/deserialize will work. :)
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:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 11L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID 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 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 InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID 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. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.
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
This question already has answers here:
What is a serialVersionUID and why should I use it?
(25 answers)
Closed 9 years ago.
Whenever we try to serialize an object of a Class, we always have a unique value for serialVersionId as a private final field, what is its significance with respect to deserialization, can we use it to check whether the object and the values have been deserialized in a proper way ?
It is used to check whether the same class definition was used for Serialization as well as DeSerialization. Straight from the documentation
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:
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 default serialVersionUID 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 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 InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID 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.
Also , check Josh Bloch's book Effective Java (2nd Edition):
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 11.)
From the doc of Serializable Object
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:
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 default
serialVersionUID 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 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 InvalidClassExceptions during
deserialization. Therefore, to guarantee a consistent serialVersionUID
value across different java compiler implementations, a serializable
class must declare an explicit serialVersionUID value. It is also
strongly advised that explicit serialVersionUID 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. Array classes cannot declare an explicit
serialVersionUID, so they always have the default computed value, but
the requirement for matching serialVersionUID values is waived for
array classes.
There is a similar Thread. Check this here
It is important when you serialize and de-serialize the same class using different VMs or on different machines. The UID is used to check, if the class you are trying to de-serialize is the really the one you think it is, so if your class in your code has one UID, and the class that was serialized has a different one, the de-serialization will fail.
A class without a UID will be given one automatically by the JVM, but there is no guarantee that different JVMs will give the same UID to the same class.
You can also refer this, which I found from SO:
What is a serialVersionUID and why should I use it?
http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does it mean: The serializable class does not declare a static final serialVersionUID field?
Java compiler warning: The serializable class [*****] does not declare a static final serialVersionUID field of type long.
Why? How to fix it?
This is explained fairly well 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.
You fix the error by adding
private static final long serialVersionUID = 7526472295622776147L; // unique id
to the class.
Further reading:
java.io.Serializable
Why should I bother about serialVersionUID? (stackoverflow)
A side note: If you're using Eclipse and if you (and no one else) ever plan to serialize your classes, you can also suppress the error by going to
Window → Preferences → Java → Compiler → Errors/Warnings
and select "Ignore" on "Serializable Class without serialVersionUID".
just add
private static final long serialVersionUID = 1L;//or some long
Docs describe it pretty well
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:
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
default serialVersionUID 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 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 InvalidClassExceptions
during deserialization. Therefore, to
guarantee a consistent
serialVersionUID value across
different java compiler
implementations, a serializable class
must declare an explicit
serialVersionUID value. It is also
strongly advised that explicit
serialVersionUID 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.
Also See
why-should-i-bother-about-serialversionuid
Declare it like that:
private static final long serialVersionUID = -4673040337179571462L;
Its required by serializable interface.
Are you extending a Swing object?
I often use the #suppressWarnings annotation to rid myself of this warning.
I guess the question of surpressing the warning or supplying a unique ID depends on the scale of your application and your intended use of Object serialisation.