views:

513

answers:

4

When I get a java.io.InvalidClassException, it gives me the serialVersionUID that it wants, and the serialVersionUID that it got. Is there an easy way to tell which of my dozens of jars using the wrong serialVersionUID?

Update: I should mention that our intention is to update everything at the same time, but I'm trying to debug a problem in our build and deploy process.

+1  A: 

The best way to deal with this kind of trouble is to update jars on the server and client side at the same time. This will guarantee the same version of your classes on both sides and you'll not have trouble when serializing / deserializing. Tracking serial UIDs each time you have this problem is not going to solve anything, you're only going to waste considerable time and resources. Its much better to spend some time and implement a proper deployment / packaging strategy.

If you really don't have any other choice, you can write a tool that loads a class from each jar (using a URLClassLoader) and then use java.io.ObjectStreamClass.getSerialVersionUID() to obtain the information you need.

entzik
+1  A: 

clumsy but works

i would use a reverse engineering tool
1) unzip the jars
2) run, say, jad on the class file tree
3) run grep or any other find tool on this new tree of source to look for the serial version uid.

anjanb
javap -private -verbose should work out the JDK box.
Tom Hawtin - tackline
+2  A: 

use the serialver tool from the sun jdk for each class in the jar.

james
+1  A: 

Bear in mind that various JVM/container/classloader combinations have different opinions on which classes should be loaded from the bootclasspath versus the application/webapp classpath.

This is complicated by the fact that serialver always loads from the bootclasspath first, so you may need to use -J-Xbootclasspath as below, to simulate different behaviour:

f=/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Classes/
serialver -J-Xbootclasspath:.:$f/dt.jar:$f/classes.jar:$f/ui.jar javax.xml.namespace.QName

Another approach is to use javap, for example:

javap -verbose -bootclasspath . javax.xml.namespace.QName | sed -n -e '/static.*serialVersionUID/{N;p;}'