On a project, we have several objects serialized. It will be necessary to use these objects on machine with different JVM (possibly different versions).
Our objects serialVersionUID are fixed and won't change, but we are concerned about the serialVersionUID of the JVM standard objects, for instance ArrayList/HashSet that are used in our serialized objects.
So the question is, can these serialVersionUID change between different versions of JVM or between different JVM ?
Or do we have to use another serialization mechanism to support different JVMs ?
The serialVersionUID should only be changed if there is a change to the class that would not be compatible with previously serialized versions of it.
To see what changes would potentially break compatibility check the Specification
I highly doubt that a new version of Java would introduce any changes to core classes that would break compatibility.
We use serialVersionUID as a version code for the class, and we should change this field when we modify the class. This field is used as identity of the class in deserialization.
For example, you serialize a object of class A and save it in an binary file, you can deserialize file to the original object later. But if you add a field to A and do not change the serialVersionUID, the deserialization may return a malformed object. And if you change the serialVersionUID, the deserialization will reject the input and throw an exception. An exception is better than a unknown error.
These error/exception happen if and only if you used an old serialization result to create a instance of a modified class. If you don't use serialization for data persistence, there won't be any problems.
Related
What happens if I serialize a Map(or List) with a java version, and I try to deserialize it with other java version, where the serialVersionUID changed? I suppose it will fail.
If you create a lib for others to use what will be the preferred way of serializing objects, using Java Objects like Map, List or using an array of self made objects?
e.g.
List<MyObject> or MyObject[]?
Map<String, MyObject> or MyObject2[] (MyObject2 contains the key and MyObject)?
If you control the class and if you did not change the serialVersionUID also deserialization of an instance of a class from a older version is possible. There for java provides a concept which is called binary compatibility. Most of the flexibility of binary compatibility comes from the use of a late binding of symbolic references for the names of classes, interfaces, fields, methods:
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/version.html
So core classes from java e.g. HashMap, ArrayList, Vector... will be deserializable even if the class will be involved in a future version of java.
If you wish to control versioning in your own class, you simply have to provide the serialVersionUID field manually and ensure it is always the same, no matter what changes you make to the classfile.
See also this article:
http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
Yes, you are correct, deserialization with changed serialVersionUID will fail. Version of JDK doesn't matter here.
If you create a lib for others to use what will be the preferred way
of serializing objects, using Java Objects like Map, List or using an
array of self made objects?
You can serialize objects to some more portable format, like plain text with (e.g. JSON, XML). You may take a look at JAXB or XStream.
But keep in mind, that main usage of serialization is to transfer objects over the network. If you would like to store some state you typically should use a database. Serialization to bytes is useful mainly for short-lived objects (because as you noticed, object may change, and thus serializationVersionId may change also).
Hope it helps.
Java specification stats that
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.enter code here
But If I assign all the classes same serial version id as follows
static final long serialVersionUID = 1L;
Now all my classes will have same serialversionUID and this will never result in InvalidclassException.
I know that we give it explicitly so that its value remains constant across different JVM implementations.
Please let me know what is the use of putting same id for all the classes and what will happen if we modify class in between serialization and deserialization ?
I believe the serialVersionUID is only used to determine the version of that class that has been serialized - the class name is always present too, so it won't lead to any ambiguity.
Please let me know what is the use of putting same id for all the classes
They're effectively unrelated values. It's just simple to use 1 and increment it every time you make a breaking change.
what will happen if we modify class in between serialization and deserialization ?
That entirely depends on the type of modification you make. If you're just adding or removing methods, or static fields, it's fine - that wouldn't affect the serialized data anyway. If you make any changes to instance fields, that's when life gets hairy. You'd need to study the serialization format in detail to work out exactly what would constitute a breaking change, but it's entirely possible that just changing the name of a field could break things - e.g. if fields are serialized in name order.
You might want to consider using a binary data format which plays a bit more pleasantly with data format changes, such as Protocol Buffers. (There are other benefits available too, such as portability and speed - and protobuf isn't the only game in town, either.)
There are 3 ways to define the serialVersionUID :
1. private static final long serialVersionUID = 1L; (Default)
2. private static final long serialVersionUID = -8940196742313994740L; (Generated)
3. Don't define serialVersionUID and let the JVM define it at runtime. #Lance Java
But I don't understand the first way!
I have seen it already, that somebody defines "serialVersionUID=1L" for all java-classes in source code.
What is the meaning? Is that useful?
If all classes have the same serialVersionUID 1L, is there no problem?
What is the meaning? Is that useful?
Yes. The point of serialVersionUID is to give the programmer control over which versions of a class are considered incompatible in regard to serialization. As long as the serialVersionUID stays the same, the serialization mechanism will make a best effort to translate serialized instances, which may not be what you want. If you make a semantic change that renders older versions incompatible, you can change the serialVersionUID to make deserializing older instances fail.
If all classes have the same serialVersionUID 1L, is there no problem?
No - the serialVersionUID is per class.
This is explain 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.
From 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:
Useful Links
java.io.Serializable
Why should I bother about serialVersionUID? (StackOverflow)
serialVersionUID in Java Serialization
The JVM will throw a InvalidClassException if the serialVersionUID of a serialized object does not match the serialVersionUID of the class it is being deserialized as.
The serialVersionUID of a class should change every time the class changes in an incompatible way. Normally this means every time you change the shape of a class (ie fields or methods change).
There are some cases where you don't want the serialVersionUID to change. For instance you might accept old versions of the object into your application. In this case, you can leave the serialVersionUID the same and new fields will come through as null.
Yes, I've seen code that defined serialVersionUID like that too. I think it is a bad idea.
In this context there is only one "distinguished" value for the serialVersionUID field; i.e. zero ... 0L. Zero means "compute the version id at runtime by applying the standard algorithm" based on the actual class that you are serializing / deserializing. That means that whenever your code's effective serialization signature changes, the serialization / deserialization code will use a different version id. From a (big picture) type safety perspective, this is the safest thing to do, though it is also somewhat inefficient, and protentially more fragile.
What is the meaning?
The 1L has no special meaning. It is just a number that will match 1L as the "other" version id.
To my mind, you are better off either using 0L, or a version number that was (at some point) generated using the standard algorithm.
If you use 0L, then you get definite deserialization exceptions if classes change in ways that could be source of problems. If you need this, it is a good thing.
On the other hand you use a generated version id, you (the programmer) can make your own decision about when to regenerate the id. And when you do decide to regenerate, the id will only change if the class signature has changed. (If classes representation etc hasn't changed, the regenerated signature should be identical to the original one!) And when the id does change, you can think about whether to add custom methods ('readObject', etc) to deal with the incompatibility.
However, if you use 1L, you can't tell if the version id needs to change without checking your code history, and comparing the old / new versions of the classes ... back as far as you need to.
Is that useful?
It depends on what you consider "useful" to mean. If you think it is a good thing to hard wire the version id to "trust me, it is ok", then 1L is useful.
My recollection is that some versions of Eclipse offer 1L as one of the possible auto-corrections for a missing serialVersionUID field warning. That is probably where the examples you see have come from.
Imagine you write a class with a serialVersionUID, instantiate it, then serialize it to a file (with ObjectOutputStream)
Then you modify the class.
Then, with the modified class, you deserialize (read in) the version you serialized before modification. Java will check the serialVersionUID of the current class and the serialized class, and if they don't match, the deserialization will fail. This is a deliberate fail-fast to prevent much more subtle (and harder to debug) errors occurring later on due to class version incompatibilities.
If you omit serialVersionUID then you disable the version checking.
If you always set if to 1L, then the check will always pass (the value is always the same) so you are still vulnerable to subtle class version incompatibility problems.
The value is used while serializing an object and de-serializing the object back into JVM.
Further, If your class changes and you don't want to support backward compatibility (i.e. able to de-serialize the object back which was serialized using your last version of class) you can change the version number to any other value.
However, to support the backward compatibility you need to keep the same version number as previously set value of serialVersionUID.
The best practice is to change the serialVersionUID, every time you have some incompatible changes to the class.
It's important to make clear the fact that having a class implement the Serializable interface makes ALL fields not declared transient part of the exported API of the class, whether or not those fields are declared private.
In other words, implementing Serializable:
breaks encapsulation. If the class has any chance to become a successful, long-lived class then you must support the serialized form ... forever.
can seriously impair your ability to evolve that class, precisely because it is a part of its exported API. The alternative is to break backward compatibility.
can create security problems for your class and its application. Deserialization represents a way for making Java objects without a constructor, so it's possible to violate a class's invariants by providing rogue byte streams to the deserialization facility.
The serialVerionUID should be thought of as a property of the serialized form. It is meant to convey to one JVM whether or not there a difference between the serialized form of a class instance that it is receiving and the serialized form of of that same class rendered (maybe) somewhere else.
You can see the potential problems that may occur if the serialized forms are different but the UIDs are the same. The receiving JVM will assume that the received serial form version between an old class and the new one are the same when they aren't and will dutifully go ahead and attempt to deserialize the byte stream.
TLDR: You shouldn't change the UID when you feel like it. You should change it when the serialized form of the class changes so that versions of software that use older versions of your class (with the different serialized form) will break instead of (possibly silently) doing the wrong thing. Not designing a good serialized form your classes will make it harder (even much harder) to provide backward compatibility for its clients. In the ideal case, the serialized form for a class persists throughout its entire evolution (and so its UID need never change).
You can assign any long value to serialVersionUID, but you have to change it every time you modify your class.
The second looks like a generated serialVersionUID, based on the features of the current class version.
Serialization is a process of transforming a object definition into a persistent format (where the format is platform specific). Objects transferred across network (RMI, EJBs) need to be serializable. SOAP requests are xml based, and JAXB is used to marshall and unmarshall the objects <---> xml. I am prompted by the code-quality plugins to add a SerialVersionUID. Is this required? Do CXF/JAXB internally need this?
JAXB does not need it, as far as I know. You get this warning because your classes implement Serializable, but JAXB doesn't require your classes to be Serializable.
If there's no other reason why your classes need to be Serializable, you could just change them so that they don't implement Serializable.
Your classes only need to implement Serializable if you want to be able to serialize/deserialize them using Java's default serialization mechanism (which is used by, for example, RMI).
There is no mention in the JAXB documentation of the need of explicitly adding a SerialVersionUID.
SerialVersionUID is a version number held by each Serializable class, which is used on deserialization to verify that the sender and receiver of a serialized object maintain compatibility as far as serialization is concerned about the classes that are loaded.
It shouldn't be required because the compiler is going to generate a SerialVersionUID by himself so you don't have worry.
The calculation is very sensible to class details so two different compilers can calculate a different SerialVersionUID and in this case a InvalidClassException could be thrown by the JVN during the deserialization process. In this case you should add the SerialVersionUID by your own. You must change the SerialVersionUID every time you modify your class to avoid de/serialization problems (that's because it is preferred not specifying the SerialVersionUID if you are always using the same compiler).
Do not be misled by what your IDE says, that's a decision of your choice based on project development requirements.
I know that I can use serialVersionUID to control the version of classes. And I read that I can then add or remove fields and the class will still be compatible, it will just use default values.
When must I change the serialVersionUID?
The value of the serialVersionUID field should ideally be changed when incompatible changes are made to the structure of the class. The complete list of incompatible changes is present
in the Java Object Serialization Specification.
To expand further, incompatible changes to a class will prevent the deserialization mechanism from creating an instance of the object, because there is information in the stream that does not map to the current class definition.
The frequently-repeated mantra about changing the serialVersionUID every time you change the class is complete and utter nonsense. See this Sun article which they republished on their site and which was migrated to the Oracle Technology Network after the acquisition.
You should change the serialVersionUID only when you deliberately want to break compatibility with all existing serializations, or when your changes to the class are so radical that you have no choice - in which case you should really think several times about what it is that you are actually doing.
In all other cases you should bust your boiler trying to use custom readObject()/writeObject() and/or writeReplace()/readResolve() methods and/or serialFields annotations so that you can continue to read objects from those existing serializations. Once you break that you are in for a major headache, indeed nightmare.
If you don't specify a serialVersionUID field in your Serializable classes, the Java compiler will specify one for you -- essentially it's a hash of the class name, interface names, methods, and fields of the class. Methods can be altered at any time, though, so if you need to change how a stored class is deserialized, you can override the readObject method. If you do specify the serialVersionUID field in your code, though, the compiler won't override that even if you do make incompatible changes, which can result in an exception at runtime -- your IDE or compiler won't give you a warning. (EDIT -- thanks EJP) IDEs such as Eclipse can insert the compiler's UID for you, if you want to easily check how the compiler views certain changes.
If you make changes often, keep an old version of the disk file around to test deserialization with. You can write unit tests to try and read in the old file, and see if it works or if it's totally incompatible.
One caveat, I've personally experienced the pain that is working with Serializable classes originally intended for long-term storage that were improperly designed. For example, storing GUI elements on disk rather than creating them when needed. Ask yourself if Serializable is really the best way to save your data.
For the sake of completeness, here's a list of changes that break the compatibility of Java serialization according to the java 8 spec:
Deleting fields
Moving classes up or down the hierarchy
Changing a nonstatic field to static or a nontransient field to transient
Changing the declared type of a primitive field
Changing the writeObject or readObject method so that it no longer writes or reads the default field data or changing it so that it attempts to write it or read it when the previous version did not.
Changing a class from Serializable to Externalizable or vice versa
Changing a class from a non-enum type to an enum type or vice versa
Removing either Serializable or Externalizable
Adding the writeReplace or readResolve method to a class
You can set serialiVersionUID to the same value for the life of the class. (Not always a good idea) Note: you can implement your own serialization version checking strategy with readObject/writeObject if you need this and leave the UID unchanged.
The only time you MUST change it is if you have already serialized some data to a file and you want to read it. If it has changed for any reason you MUST set the serialiVersionUID to the version in the file to have any hope of being able to read the data.
To declare your own serialVersionUID in java, type this in the
serialized object class:
#Serial
private static final long serialVersionUID = desired_number;