In Java, static and transient fields are not serialized. However, I found out that initialization of static fields causes the generated serialVersionUID to be changed. For example, static int MYINT = 3;
causes the serialVersionUID to change. In this example, it makes sense because different versions of the class would get different initial values. Why does any initialization change the serialVersionUID? For example, static String MYSTRING = System.getProperty("foo");
also causes the serialVersionUID to change.
To be specific, my question is why does initialization with a method cause the serialVersionUID to change. The problem I hit is that I added a new static field that was initialized with a system property value (getProperty). That change caused a serialization exception on a remote call.
You can find some information about that in the bug 4365406 and in the algorithm for computing serialVersionUID. Basically, when changing the initialization of your static
member with System.getProperty()
, the compiler introduces a new static
property in your class referencing the System
class (I assume that the System
class was previously unreferenced in your class), and since this property introduced by the compiler is not private, it takes part in the serialVersionUID
computation.
Morality: always use explicit serialVersionUID
, you'll save some CPU cycles and some headaches :)
Automatic serialVersionUID is calculated based on members of a class. These can be shown for a class file using the javap tool in the Sun JDK.
In the case mentioned in the question, the member that is added/removed is the static initialiser. This appears as ()V in class files. The contents of the method can be disassembled using javap -c. You should be able to make out the System.getProperty("foo") call and assignment to MYSTRING. However an assignment with a string literal (or any compile-time constant as defined by the Java Language Specification) is supported directly by the class file, so removing the need for a static initialiser.
A common case for code targeting J2SE 1.4 (use -source 1.4 -target 1.4) or earlier is static fields to old Class instances which appear as class literals in source code (MyClass.class). The Class instance is looked up on demand with Class.forName, and the stored in a static field. It is this static field that disrupts the serialVersionUID. From J2SE 5.0, a variant of the ldc opcode gives direct support for class literals, removing the need for the synthetic field. Again, all this can be shown with javap -c.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With