EDIT : solved using this solution
I have a very strange problem. I'm trying to deserialize a HashMap with two classes that have since been changed, though not to any large degree. Can't post code because it's under copyright.
Notably the constructor of Class 2 has an added field (String name) since the file I'm trying to deserialize was serialized.
It seems like Class 1 is trying to be cast to String as the name field of Class 2.
I've always been using ObjectInputStream and ObjectOutputStream. The part that has me mystified is that Class 1 has never had a member variable of type Class 2, and the HashMap types have always been in the order . I don't really know what's going on, so I tried a solution posted in this question that had the same exception as I'm getting, but despite lots of research on ClassLoaders, I still don't really understand and didn't really know what ClassLoader to use as the "free variable".
Here is the stack trace (class names changed) of the problem I'm encountering:
java.lang.ClassCastException: cannot assign instance of [CLASS 1] to field [CLASS 2].name of type java.lang.String in instance of [CLASS 2]
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2034)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1207)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1975)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
at java.util.HashMap.readObject(HashMap.java:1030)
at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:969)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1775)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1327)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:349)
Code snip:
final ClassLoader loader = this.getClass().getClassLoader(); //attempt to solve ClassCastException issue below.
FileInputStream fin = new FileInputStream(targetFile);
InputStream buffer = new BufferedInputStream(fin);
ObjectInputStream ois = new ObjectInputStream(buffer) {
/*
* As seen here: https://stackoverflow.com/questions/2358886/how-can-i-deserialize-the-object-if-it-was-moved-to-another-package-or-renamed
*/
@Override
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
if (resultClassDescriptor.getName().equals("Class 1 [old path]"))
resultClassDescriptor = ObjectStreamClass.lookup(Class 1 [new path].class);
else if (resultClassDescriptor.getName().equals("Class 2 [old path]"))
resultClassDescriptor = ObjectStreamClass.lookup(Class 2 [new path].class);
return resultClassDescriptor;
}
/*
* As seen here : https://stackoverflow.com/questions/9110677/readresolve-not-working-an-instance-of-guavas-serializedform-appears
*/
@SuppressWarnings("rawtypes")
@Override
protected Class resolveClass(ObjectStreamClass objectStreamClass)
throws IOException, ClassNotFoundException {
return Class.forName(objectStreamClass.getName(), true, loader);
}
};
Object ob = ois.readObject(); //exception happens here
HashMap<Class 1, Class 2> loadedMap = (HashMap<Class 1, Class 2>)ob;
ois.close();
buffer.close();
fin.close();