2

A few months back I serialized a java.io.Serializable object into a file. Now I need to read the contents, but since then the serialVersionUID has changed, and now I'm getting a "class incompatible" error. I know for a fact that none of the data members have changed, so the only barrier is the serialVersionUID check.

Is there a way to either disable the check or to modify the serialVersionUID in the binary file?

CLARIFICATION

This question is assuming that I can't edit the source. Is there a way I can hack the .class file or perhaps hack the serialized object file (use a hex editor and change a value at some certain offset)?

Daniel Fortunov
  • 43,309
  • 26
  • 81
  • 106
bajafresh4life
  • 12,491
  • 5
  • 37
  • 46

4 Answers4

2

Why not modify the serialVersionUID in your current version instead as described in the Serialization documentation?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The way his question was written indicates that the object is not under his control to be able to make that change. – Matthew Brubaker Jan 14 '09 at 22:21
  • But if that is the case, then yes. Changing the serialVersionUID back to what it was when he wrote the data out would allow him to read it back in. – Matthew Brubaker Jan 14 '09 at 22:22
  • It doesn't matter if the class isn't under his control. He can just write a new one with the same name, members, and serialVersionUID – Adrian Pronk Jan 14 '09 at 22:30
  • This will work only if the class has no elements that will break on deserialization from the old vers. If you remove a member variable and try to fool it with serialVersionUID it will throw an Exception deserializing from the old files. – Steve B. Jan 18 '09 at 02:23
  • @SteveB: Read the question: " I know for a fact that none of the data members have changed, so the only barrier is the serialVersionUID check." – Jon Skeet Jan 18 '09 at 07:38
2

As a hack, you can generate the serialVer your jvm is probably using using the serialver tool:

serialver -classpath whatever com.foo.bar.MyClass

If you then manually set the serialVerUID in your class it ought to match and you ought to be able to load, assuming you haven't changed the class in such a way as to invalidate.

Steve B.
  • 55,454
  • 12
  • 93
  • 132
  • For this to work, you need access to the class file as it was when the object it was serialized. Hopefully it's in the Version Control archive? – Adrian Pronk Jan 14 '09 at 22:28
  • You could also write your own readObject, I think that you'd probably be able to read the fields in declared order. – Steve B. Jan 14 '09 at 22:31
2

I recently found myself in a similar situation--I had some serialized objects that I had to read, the serialVersionUID of those objects was different than the newest version and, in my case, there were a couple of different serialVersionUIDs stored in the file for the same class (stored at different times, obviously). So I didn't have the luxury of modifying the class and setting its serialVersionUID; I actually had to go in and modify the stored data.

What I figured out (by reading the java.io source code) is that an object gets serialized by first storing the class name (using writeUTF()) and then immediately after using writeLong() to save the serialVersionUID.

My solution was to catch the exception then go back, look for the class name, and immediately after the class name replace the old serialVersionUID with the new.

-3

It is documented that Serialization is not intended to be used for persisting data. In order to get that data back, you will need to downgrade your version of the JVM to the version that was used to output that data.

For future reference, don't use serialization to persist data between sessions of the JVM.

Matthew Brubaker
  • 3,097
  • 1
  • 21
  • 18
  • You *can* use serialization in this manner as long as you set the serialVersionUID. From the Serializable doc - "Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value." – CurtainDog Apr 16 '09 at 13:19
  • This might be true, taking into consideration that you cannot access and get your data back if you update your class. What you have to do is load your data with a non-updated version of your class and pass it to the new class and serialize again (during runtime) which is not viable in most situations. – mostruash Feb 22 '13 at 13:49