Is it possible to get serialVersionUID of the java class in runtime
Asked Answered
S

4

11

It's well known that runtime will genereate serialVersionUID field for your class, if you failed to explicitly define it.

But is it possible to get this value in runitme? Is it possible in runtime, having reference to .class, obtain it's serialVersionUID?

Selfimmolating answered 4/3, 2014 at 10:27 Comment(5)
What do you want this information for, if I may ask? It is used internally by the JVM for {de,}serialization, you shouldn't have to care about it...Implicit
Of course it's possible. ObjectInputStream does it.Cleancut
@Implicit I expected this question. Actually, I use infinispan cache library with file cache, which forces me to use serializable class. Serializable instances of these classes survives JVM restart. The problem is that when I change internal structures of the file and update serialVersionUID, infinispan is still capable to deserialize this instances to application, which is a problem.Selfimmolating
@Implicit I wrote code, which manually checks serialVersionUID and skips deserialization instances of old versions of class. The only problem that I need to manually keep track on changes of the class. What I want - to force my code change serialVersionUID automatically.Selfimmolating
@Implicit typo "when I change internal structure of these classes"Selfimmolating
S
26
 Integer i = new Integer(5);
 long serialVersionID = ObjectStreamClass.lookup(i.getClass()).getSerialVersionUID();

Above is the sample code to get serial version id of the class at runtime.

Senarmontite answered 4/3, 2014 at 10:32 Comment(3)
Perfect! That's actually does what I wanted.Selfimmolating
Note however the docs: > "Null is returned if the specified class does not implement java.io.Serializable or java.io.Externalizable." You'd maybe assume that classes that are to be serialized implement this interface but it seems some frameworks use other marker mechanisms.Gallous
Optional.ofNullable(ObjectStreamClass.lookup(c)).map(ObjectStreamClass::getSerialVersionUID).orElse(0L))Hepplewhite
B
2

Sure you can. serialVersionUID is a regular static variable, so you can access it when you want. The only problem is that it is typically defined as private or protected, so you can access it from the class itself only. To access it from outside you can use reflection:

Class<?> clazz = obj.getClass();
Field f = clazz.getDeclraredField("serialVersionUID");
f.setAccessible(true);
long uid = (long)f.getValue();
Belshazzar answered 4/3, 2014 at 11:10 Comment(4)
Are you sure? I get java.lang.NoSuchFieldException: serialVersionUIDSelfimmolating
In fact I'm trying to force java runtime to create this field for class which has not explicitly specified it.Selfimmolating
@Kite It already does that, automatically. There are serious problems with your question and your approach. See my answersCleancut
On the other hand this is the only way I've found to get to know if the class defines own serialVersionUid or uses the one automatically generated by the compiler.Pharmacopsychosis
C
2

What I want: to force my code [to] change serialVersionUID automatically ... when I change internal structure of these classes.

No you don't. You want to keep the serialVersionUID the same forever, and to restrict the internal changes to what can be handled automatically by Serialization, for which you need to consult the Versioning chapter of the Object Serialization Specification. Changing the serialVersionUID on every class change is an urban myth which unfortunately has been far too widely propagated and accepted.

And your proposed solution won't work either. 'Skipping deserialization instances of old versions of [a] class' isn't a solution to anything. Serialization will already have rejected it with an exception if the serialVersionUIDs don't agree. Anything you do after that is already too late.

This is sounding like an XY problem. You want to do X, you think Y is the answer, so you ask about Y, when you should be asking about X. For the correct solution see above.

Cleancut answered 4/3, 2014 at 23:53 Comment(2)
I have Serialization Proxy Class, which is serialized manually with NON-JDK serialization framework. I have two methods which manually serialize-and-de-serialize this proxy. In these methods I serialize class version, serialize the object itself (this time using standard JDK serialization). For me it's way more convinient to throw away cached instances if they are from previous version of the class. Anyway - thank you for the link about versioning chapter, I will investigate it deeperSelfimmolating
You needed to provide a lot more of this detail in your question. Otherwise everybody just wonders what you're doing it all for.Cleancut
H
0

Here comes a slightly modified version of the accepted answer regarding the nullability of the ObjectStreamClass#lookup method.

Optional.ofNullable(ObjectStreamClass.lookup(c))
        .map(ObjectStreamClass::getSerialVersionUID)
        .orElse(0L))
Hepplewhite answered 22/3 at 4:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.