Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regarding serialization, serialVersionUID, and incompatible class

Tags:

java

android

I saw a few related questions and answers here, but they didn't seem to help. So I guess I need to post a separate question here:

I have a serializable class MyDataClass, which contains a few more serializable inner classes. I save it to a file by using FileOutputStream and ObjectOutputStream. When reading it back, I sometimes get an exception (maybe ClassNotFoundException or InvalidClassException but I'm not sure), and the exception's message goes like this:

12-01 18:44:16.479: D/My App Name(534): ***** exception occurred 
com.xyz.myapp.lib.am; Incompatible class (SUID): com.xyz.myapp.lib.am: 
static final long serialVersionUID =3894560643019408205L; but expected 
com.xyz.myapp.lib.am: static final long serialVersionUID =-4215454881436014736L;

MyDataClass is something like this:

public static class MyDataClass implements Serializable {

    private static final long serialVersionUID = 0x98F22BF5;
    .....
    public boolean bNoTitle;
    public short syncOption;
    .....

    public class InnerClass implements Serializable {
        private static final long serialVersionUID = 0x99D32720;
        double premium;
        double interest;
    }
}

Then I used the following code to read it:

MyDataClass oc;
FileInputStream fin = new FileInputStream(dataFile);
ObjectInputStream ois = new ObjectInputStream(fin);
oc = (MyDataClass)ois.readObject();
ois.close();
fin.close();

An exception is thrown by readObject, NOT EVERY TIME, but sometimes that I can't pinpoint so far. I read somewhere that the serialVersionUID that's actually written into the file is not what I assigned in the code. So when it's read back, the UID does not match, and thus the exception. Is that right? If so, how can I ensure that there is no exception and the object is read back as expected?

thank you.

EDIT: It seems that when debugging from Eclipse, it was all fine. But after I made a build using ant, the problem would surface. But not every time after an ant build, but sometimes.

EDIT: I saw in another post:

Are you reading from a file? In that case, it does not matter if you added the serialVersionUID now, it is different from the one stored in the file, and that creates the exception. A quick solution could be to set serialVersionUID to 4209360273818925922L, which seems to be the serialVersionUID that was automatically generated by java when you saved those object in that file at that time.

My file will be saved/read many times when the user uses the app. If Java assigns a different UID every time the file saves, then how can I wire-in a number in the code before hand? I need a truly static UID that doesn't change, even after an ant build.

like image 280
wwyt Avatar asked Dec 02 '11 05:12

wwyt


2 Answers

I agree with AKJ:

I think that for your first problem 'class not found' - you are probably deserializing the class in an enviornment which doesn't know this class. It is also possible you have 2 enviornments with 2 copies of the class.

AnyHow, serialization's UID works like this: If you haven't specified one, it will generate one automatically every time you compile/build - otherwise, if you have specified one, then that one is the UID.

Note that AJK could be right without you knowing it -- Every class member from your class is serialized by default, unless upon declaring it you specify transient. So, if you have short, long, String, myClass or whatever, they will all go through serilization. According to the explaiation above, if no constant UID is set, every time you compile ypu shall get a different UID - and this is likely to cause your problem.

good luck.

like image 113
user967710 Avatar answered Sep 19 '22 18:09

user967710


As you are explicitly declaring the serialVersionUID there should be no problem in serializing and deserializing as long as the serialVersionUID is not changed (and class has not changed drastically).

From the exception message I feel that you may be having some member class that is also getting serialized but does not have explicit serial version UID, so you may need to explicitly declare the serialVersionUID in that class as well.

Another possibility is that you may be accidently trying to read a file that was saved before you put explicit serialVersionUID.

like image 20
Ashwinee K Jha Avatar answered Sep 22 '22 18:09

Ashwinee K Jha