Is serialVersioUID require in Interfaces(I hope not)? - java

My understanding is serialVersionUID is applicable only to classes, because we can create an object only to classes and the concept of serialVersionUID is for object serialization and deserialization.

It is not required, and more importantly, it will not have any effect on how serialization works in your application.
Since serialVersionUID should be static, even if you add it to your interface, it won't be inherited, so you'll need to add one to your implementing class, too. Similarly, if you extend a serializable base class, you need to add serialVersionUID again.

Related

Can Java Serialization UID numbering start at 1

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.

Local class incompatible error when only a method has changed

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.

Serialization of an Object of a class on 2 different JVMs in java

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

Importance of serialVersionId in Serialization? [duplicate]

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

Serialisation and sub-classes

If I define a class as Serialiable then when I create a sub-class it asks me to define a serialVersionUID. Is this necessary or can I rely on the one in the super-class?
I used to declare once SerialVersionUID in separate (possibly top class), like:
public static final long GlobalSerialVersionUID=0L;
And then in each Serializable class declare:
private static final long serialVersionUID = MyTopClass.GlobalSerialVersionUID;
this approach would guarantee that you will all time have the same SerialVersionUID and if you will be going to implement data interchange between different serialized versions - you could branch code between different serialized versions.
SerialVersionUID is used if you change the implementation of a class, but still want to be able to serialize/deserialise objects saved in the "old" format. So this means that you have to implement it in the subclass as well, if you want to change the subclass but not the superclass. However, if you dont need this "version control" you dont have to use SerialVersionUID at all.

Categories