编辑:使用此解决方案解决
我有一个非常奇怪的问题。我正在尝试反序列化具有两个已更改的类的 HashMap,尽管程度不大。无法发布代码,因为它受版权保护。
值得注意的是,类 2 的构造函数有一个附加字段(字符串名称),因为我试图反序列化的文件已被序列化。
似乎 Class 1 正试图转换为 String 作为 Class 2 的名称字段。
我一直在使用 ObjectInputStream 和 ObjectOutputStream。让我感到困惑的部分是 Class 1 从来没有 Class 2 类型的成员变量,而 HashMap 类型一直是有序的。我真的不知道发生了什么,所以我尝试了在这个问题中发布的解决方案,该解决方案与我得到的异常相同,但是尽管对 ClassLoaders 进行了大量研究,但我仍然不太了解,也没有真正了解知道使用什么 ClassLoader 作为“自由变量”。
这是我遇到的问题的堆栈跟踪(类名已更改):
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)
代码片段:
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();