Java static serialization rules?
static
s are implicitly transient
, so you don't need to declare them as such.
Serialization is for serializing instances, not classes. static
fields (methods are irrelevant since they are part of the class definition so they aren't serialized) will be reinitialized to whatever value they are set to when the class is loaded.
If you have a mutable static
field, then the changes made to that value will be lost.
How to serialize static data members of a Java class?
The first question is why you need to serialize the static members?
Static members are associated with the class, not the instances, so it does not make sense to include them when serializing an instance.
The first solution is to make those members not static. Or, if those members are the same in the original class and the target class (same class, but possibly different runtime environments), don't serialize them at all.
I have a few thoughts on how one could send across static members, but I first need to see the use case, as in all cases that means updating the target class, and I haven't found a good reason to do so.
Are static variables serialized in Serialization process
serialVersionUID is a special static variable used by the serialization and deserialization process, to verify that a local class is compatible with the class used to serialize an object. It's not just a static variable as others, which are definitely not serialized.
When an object of a class is first serialized, a class descriptor containing among other things the class name and serial version UID is written to the stream. When this is deserialized, the JVM checks if the serial version UID read from the stream is the same as the one of the local class. If they're not, it doesn't even try to deserialize the object, because it knows the classes are incompatible.
Static method call within a Serializable object
Yes, this will work. toString()
is never called by Java's built-in serialization framework, so it can basically do whatever it wants.
Most of the time, a serialized object is just copied field-by-field, without any methods of the object being invoked. A class can change this default behavior by implementing special methods (see http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html for details), but that's not the case in your example. So whatever your methods are doing (not only toString()
), it doesn't matter for serialization.
Now to the second question: what happens if ReflectionToStringBuilder
is not in the classpath? That's simple: nothing happens. As long as ReflectionToStringBuilder
is not used (i.e. any of its static methods are invoked, or you're creating an instance of it), that class is not loaded (or at least not linked), so it doesn't matter if it's present or not. Only when you try to actually use that class will you get a NoClassDefFoundError
. So deserializing your object will work, but if you call toString()
, you get an exception.
Why SerialVersionUID is static
Because any of the object variables/members can be accessed once Object is successfully created. You can't access Object variables without creating it. Now back to question, during deserialization, Object needs to be created from the data. If there's no way to check whether object is deserializable, there's no way to get the Object members.
For the same reason, UID is made as static.
What is a serialVersionUID and why should I use it?
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.
Do all variables in a serialized class become part of the serialization process in Java?
Serialization with the marker interface you mentioned is a tough topic in Java. All member fields of an object will get serialized, except the ones marked with the keyword transient
. Other variables like local variables or parameters to constructors or methods are not serialized.
It is easy to corrupt a Java program by deserializing malicious or corrupted data. You can customize, what will be serialized by implementing the methods private void readObject(ObjectInputStream s)
and private void writeObject(ObjectOutputStream s)
As you can see, those private (!) methods are not members of the interface Serializable
, so it's compiler magic that calls them for serialization. If you do not implement them, there is a default implementation.
Don't forget to specify the variable
private static final long serialVersionUID = 1L;
and give it a new value for each update of your member fields - this will prevent that you deserialize data from another version of your class where the data does not suite the implementation.
In general: If you really have to use serialization, I would recommend that you read more articles on it, e.g. https://ahdak.github.io/blog/effective-java-part-11/ - it summarizes from the book "Effective Java" by Josh Bloch.
Also the Java Object Serialization Specification could be interesting for you.
force serialization of static fields
You could write a method to use reflection to serialize all static methods. A static method can be marked transient which would normally be redundant, but you could use this to highlight static fields you don't want to serialize. You can call this method from your writeObject() to save you having to do this for every field.
What does it mean: The serializable class does not declare a static final serialVersionUID field?
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 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 named"serialVersionUID"
that must be static, final, and of type long:
You can configure your IDE to:
- ignore this, instead of giving a warning.
- autogenerate an id
As per your additional question "Can it be that the discussed warning message is a reason why my GUI application freeze?":
No, it can't be. It can cause a problem only if you are serializing objects and deserializing them in a different place (or time) where (when) the class has changed, and it will not result in freezing, but in InvalidClassException
.
Related Topics
Stop Scheduled Timer When Shutdown Tomcat
Remove Last Character of a Stringbuilder
How to Implement Infinity in Java
Sessiontimeout: Web.Xml VS Session.Maxinactiveinterval()
What Is the Equivalent of Java Static Final Fields in Kotlin
Specific Difference Between Bufferedreader and Filereader
Invalid Syntax Error "Type= Myisam" in Ddl Generated by Hibernate
Capture Generated Dynamic Content at Server Side
Data Structures That Can Map a Range of Keys to a Value
How to Cast an Object to an Int
Download Attachments Using Java Mail
Print All the Spring Beans That Are Loaded
Extract Source Code from .Jar File
Java Switch Statement Multiple Cases
How Much Memory Does a String Use in Java 8