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.
Related
I'm trying to learn how the serialization works with Java and its lastest version. I'm trying to serialize a lambda like this :
Runnable r = (Runnable & Serializable)() -> {System.out.println("This is a test");};
But I notice that I have no warning about the absence of a serialVersionUID variable. Is it normal ?
I know it will be generated at the runtime however it is strongly recommended to define it : https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html
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.
What should I do ? How can I define it in my Lambda ?
Thanks
The serialVersionUID is only relevant to classes which generate a stream identifier. This is not the case if the serializable class has a writeReplace() method (also described in the Serializable documentation) that returns a substitute object of a different class, as such a representation is fully decoupled from the original class. This is what happens with serializable lambda instances, see SerializedLambda:
Implementors of serializable lambdas, such as compilers or language runtime libraries, are expected to ensure that instances deserialize properly. One means to do so is to ensure that the writeReplace method returns an instance of SerializedLambda, rather than allowing default serialization to proceed.
So it’s an instance of SerializedLambda that ends up on the stream and thus the responsibility of that class to have a stable serialized representation. Unfortunately that doesn’t protect you from possible incompatibilities.
Upon deserialization, a synthetic method of the class defining the lambda expression will get called (compare to this and this answer) which will reject deserialization attempts which do not match an existing definition of a lambda expression within that class, whereas the matching may depend on subtle aspects of the lambda’s definition. Note that even recompiling the defining class with Eclipse rather than javac might break the Serialization compatibility.
Not also the security impacts of Serializable lambdas. Generally, I recommend to avoid using it.
This question already has answers here:
What is a serialVersionUID and why should I use it?
(25 answers)
Closed 8 years ago.
I'm currently trying to justify the removal of the rule in findbugs/sonar that classifies making a class serializable, or in most of our cases, extending our base class that makes the classes serializable without the dev realising, then not defining a SerialVersionUID a critical error!
This of course makes our muggle management (read management that are not developers) panic, thinking we have critical bugs that must be fixed!
My argument is that in the current versions of Java, you do not need to provide a SerialVersionUID as the JVM will do that for you in cases where you serialize a class, but can anybody point any reasons why in todays day and age we should still provide a UID ourselves rather than leave it to the JVM? Looking on the web, the only reasoning I can really find for providing a UID nowadays is that not doing it is 'bad practice'.
Any ideas?
SerialVersionUID is used to check whether the version of class used for serializing and de-serializing is same or not across different JVM's.The default value generated by Serializable Runtime is sensitive to class details.So,although the classes loaded across different JVM may be compatible,but still you can get a false InvalidClassException .
Check the Javadoc:-
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.*
I wanted to extend my comment but ran out of room.
nb These aren't my original thoughts, but rather from Joshua Bloch's Effective Java
Reason 1: Serialized objects can persist
Even small, otherwise trivial changes to the class will cause the JVM to generate a different ID. So when you try to deserialize an object serialized with an older but otherwise compatible class structure, the result is an InvalidClassException.
Changing something as innocuous as adding a convenience accessor to a class will force a different UID to be computed. Similarly, one of the things that influence the generated UID are private members. So not only are you restricted from changing the public facing API (which may be preferable), but you're also restricted from changing too drastically any private implementation details, for risk of causing a UID mismatch.
The other way to look at this is that by manually defining an UID, while you can ensure that the JVM will attempt to deserialize an object with its intended class, regardless of the changes to your class, you can also prevent the JVM from attempting to deserialize an object with its intended class (eg your new class is incompatible) by changing this UID.
Reason 2: Runtime computation is more expensive
Computed UIDs are computed at runtime. Manually specifying this field obviates this computation.
The central purpose of defining serialVersionUID is to control serialization compatibility. As other answers and the documentation has noted, unless a specific value is declared, the value is computed from a variety of class characteristics, even ones that don't actually affect the serialized form, such as the signatures of public methods. If you don't provide a serialVersionUID, and one or more of these characteristics of the class differs between serialization and deserialization, an InvalidClassException will be thrown.
Now to the question of when one should or should not declare a serialVersionUID.
If you care about serialization compatibility, you should almost always declare a serialVersionUID. Doing this is the only possible way to evolve the class and have the serialized form be compatible with other versions of the class. You will probably also have to provide custom readObject and writeObject methods and use various mechanisms like readFields, putFields, and serialPersistentFields to control the serialized format, and to cope with potential changes to the serialized format.
By "care about serialization compatibility", suppose you've serialized an object and have stored it in a file or database. Do you expect to have future versions of your system (with evolved versions of the classes) be able to read the stored serialized objects? Or, suppose you serialize objects and send them over a network to other applications that deserialize them. This happens in RMI, or it could happen if you develop your own network protocol that sends and receive serialized objects. If so, then on your network, can you have different versions of your application running in different places on the network, and do you expect them to be able to talk to each other successfully?
If any of the above are true, you care about serialization compatibility, and you need to declare serialVersionUID.
There are times when you might care about serialization compatibility but when it doesn't make sense to declare a serialVersionUID. One example is with anonymous inner classes. Such a class can be made serializable, but it's impractical to try to make it compatible, for several reasons. Anonymous inner classes have compiler-generated names that are implementation specific. They can also change across recompiles. AICs also contain references to their enclosing instance and references to any objects that might be captured from the local scope. All of these objects, and their transitive closure, become part of the serial form of an AIC. For these reasons it's a bad idea to serialize AICs, let alone try to achieve serial compatibility for them. In such cases, adding a serialVersionUID is just a distraction. If you are tempted to serialize AICs, you probably want to restructure the code to serialize something else instead.
There might be times when you don't care about serialization compatibility of different class versions at all.
One example is if you have a closely coupled set of JVMs that are all sharing classes from the same classpath, and they're exchanging serialized objects. Since they are using the same actual classes, there can't be any incompatibility. Declaring a serialVersionUID for classes in this case is useless busywork. In fact, doing so may conceal errors. In such a multi-JVM scheme, if there is a serialization compatibility error, that indicates some kind of configuration problem, since it means the JVMs are using different classes. You'd want that to be detected as soon as possible, and not declaring serialVersionUID would cause an error to be manifested more quickly.
Another reason is that Serializable is inherited, which may cause classes down the inheritance tree to become Serializable even if they are never intended to be serialized. Again, declaring serialVersionUID for such classes is useless busywork. There's no formal way for a class to reject its inheritance and "undeclare" serializability. Best practice, though, is for such classes to implement readObject and writeObject and for them to unconditionally throw an exception like InvalidObjectException or NotSerializableException.
Still another example is that your product requirements (or whatever) might simply decide not to care about serialization compatibility in certain cases or not at all. It's something that you might decide is just "not supported." The JDK itself has taken this approach. In general, most public, serializable classes in the JDK are constrained to be forward and backward serialization compatible. As such, all of these classes declare a serialVersionUID and take care to deal with missing or added fields. However, some portions of the JDK, most notably AWT and Swing, are explicitly not serialization compatible across releases. Such classes have a disclaimer that warns of serial incompatibility, and instead of declaring a serialVersionUID, these classes include an annotation #SuppressWarnings("serial") to eliminate the warnings.
Bottom line is that it's a mistake to slavishly declare serialVersionUID in every class that happens to inherit Serializable. There are good reasons to declare it, and there are also good reasons not to declare it. You should decide explicitly.
This question already has answers here:
What is a serialVersionUID and why should I use it?
(25 answers)
Closed 9 years ago.
I'm creating a Java application, and when creating an interface to use with an ADT, it finds the need to initialize a random number as an ID number.
public class StackFullException extends RuntimeException {
private static final long serialVersionUID = 1L;
public StackFullException(){}
public StackFullException(String message) {
super(message);
}
}
I'm curious as to whether leaving this out will impact anything consequential about my program and if so, how to avoid it.
The serialVersionUID is part of the black magic of the Java serialization API.
It is used to uniquely identify a version of the class so that when a class is de-serialized the version can be checked against the version of the class loaded by the ClassLoader.
The serialization API will generate a serialVersionUID itself if none is specified but this is then subject to random change by inconsequential changes (or at least ones that don't break serialization compatibility).
Adding the field yourself gives you control over this process - you decide when a change to the class should break de-serialization of older versions.
More information can be found in the JavaDocs for Serializable.
In short, if you plan to serialize this class and then de-serialize it later - but after making some changes to code and recompiling etc - this field is more-or-less essential to guarantee that this will work as intended.
The Serializable interface gives enough detail in this regard:
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.
Also you can read more about this in Java Object Serialization Specification
searialVersionUID is just a version number you place on the interface to know it's communicating with the same API. In other words, if the client's Java Object is "1L" and the server's is "2L" then it will throw a missmatch error.
UIDs in this context can also be used to distinguish between two objects being written to disk.
Source: http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/
As others have said, the UID is optional and shouldn't impact your program.
It's used to reflect structural changes to the class when used with the JDK's serialization. It's completely optional to use. Personally, I never create such fields and often delete them when I find them.
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
Why isn't the serialVersionUID automatically generated? I was running into an issue on an application server where apparently an old class was being cached.
serialversionuid is not automatically generated because it is dangerous. When serialversionuid is set, it implies that two versions of a class are compatible with respect to serialization.
Imagine you have a class called Foo, and it has no serialversionuid (the default), and you serialize an instance of Foo to a file. Later, you add some new members to the Foo class. If you try to deserialize the Foo object from the file, you will get a serialization failure stating that the objects are incompatible. They are incompatible, this is what you want and is the default. They are incompatible because new members in the Foo class cannot be initialized from the old serialized instance of Foo.
Now, you might say, "I don't care, in my application it is acceptable for those fields to be uninitialized". If that really is the case, you can set the serialversionuid of the new Foo class to be the same as the old Foo class. This will tell Java that the objects are compatible with respect to serializablity, and Java will not complain when you deserialize the old Foo instance into the new Foo class (but the new fields will still be uninitialized).
If you are creating a new class for the first time, and you set the serialversionuid, you are entering a contract. That contract is, "For all future versions of this class with the same serialversionuid, I will guarantee they are compatible with respect to state and serialization".
If you change a class, and you explicitly want to disallow deserialization of old versions, you can change the serialversionuid to a new value. This will cause an exception to be thrown if an old object is attempted to be deserialized into a new class instance.
It is automatically generated, based on the structure of the class. If the structure changes, the id is regenerated (according to the serialization specification it is a hashof the class).
So you'd better define an explicit serialVersionUID.
If you're using Eclipse as your IDE, you can right-click on the warning about the missing serialVersionUID and you'll get two options:
1) Define the Eclipse default, which has the value 1L; or
2) Define a randomly generated long value
If you care about versioning of serialized objects, you'll need to manually regenerate a new value each time you modify the class. The Javadoc for the Serializable interface has this to say about what happens if you don't declare a serialVersionUID at all:
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.
In practice, I've found that even if you start with identical source code on two or more machines (checked out of Subversion, for example) where serialVersionUID was undefined in a class, the compiler-generated value in the class is different on each machine when the code is compiled. This can cause confusing errors during development.
If you are sure that you'll never have a situation where you have stale serialized objects that are out-of-sync with a newer version of the class (or two JVMs sending out-of-sync serialized objects to each other, perhaps across a network or socket connection) then just set a value of 1L for serialVersionUID and leave it that way forever.
http://download-llnw.oracle.com/javase/6/docs/api/java/io/Serializable.html