Java Static Serialization Rules

Java static serialization rules?

statics 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 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.

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 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:

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



Leave a reply



Submit