在程序的新运行中重新加载时出现 Java 序列化错误,但不是在同一次运行中

标签 java serialization guava

我遇到了一个奇怪的情况,当我成功序列化某个对象然后在另一个程序中反序列化它时,我在反序列化时遇到以下错误:

Exception in thread "main" java.lang.ClassCastException: cannot assign instance of com.google.common.collect.ImmutableList$SerializedForm to field MyClass.featureExtractors of type com.google.common.collect.ImmutableList in instance of MyClass
        at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2063)
        at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1241)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1970)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
        at my code which calls readObject

奇怪的是,如果我将测试代码添加到序列化数据的程序中以立即重新打开文件并反序列化它,它会毫无问题地成功。

这是编写程序的序列化代码(和反序列化测试):

final FileOutputStream fos = new FileOutputStream(outputModelFile);
final ObjectOutputStream oos = new ObjectOutputStream(new GZIPOutputStream(new BufferedOutputStream(fos)));
oos.writeObject(processedData);
oos.close();

System.out.println("Reloading");
final FileInputStream fin = new FileInputStream(outputModelFile);
final ObjectInputStream ois = new ObjectInputStream(new GZIPInputStream(new    BufferedInputStream(fin)));
final MyClass ret = (MyClass) ois.readObject();
ois.close();

阅读程序中的反序列化代码如下:

final FileInputStream fin = new FileInputStream(f);
final ObjectInputStream ois = new ObjectInputStream(new GZIPInputStream(new BufferedInputStream(fin)));

final MyClass ret = (MyClass) ois.readObject();
ois.close();

被序列化和反序列化的结构非常复杂,有几个子对象涉及自定义writeObject/readObjectreadResolve。似乎如果 writeObject/readObject 对中有错误,它应该会在任何反序列化尝试中失败。一个坏的 readResolve 更合理,但唯一涉及的 readResolve 只是做一种字符串驻留的形式,它不涉及抛出异常的对象。我正在慢慢尝试拆开这些部分并逐个测试它们的序列化,但我想知道是否有人知道什么会导致这种奇怪的行为?

附言this question 中讨论了类似的异常。 , 但这是由于所讨论的字段涉及循环引用,这在此处没有发生。

更新:当然,在我发布这篇文章十分钟后,我就明白了。这两个程序位于不同的 Maven 模块中。写入程序与正在写入的对象位于同一模块中,但读取程序位于另一个依赖于另一个模块的模块中。这表明存在某种类不匹配的可能性。

最佳答案

写入和读取程序使用不同版本的 Guava,序列化形式在版本之间不兼容。 Guava 文档对此发出警告,但我忘记了:

Serialized forms of ALL objects are subject to change. Do not persist these and assume they can be read by a future version of the library.

关于在程序的新运行中重新加载时出现 Java 序列化错误,但不是在同一次运行中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20005194/

相关文章:

c# - 如何使用默认命名空间反序列化 xml?

generics - 如何使用 Guava Optional 作为 "naturally covariant object"

rest - Guava LoadingCache 与 Kotlin 协程

java - eclipse插件执行中出现NoClassDefFoundError

java - java x 选项中的 JOptionPane

java - Java中存储KeyStore : empty file and unable to reload

c# - 使用事件序列化类

java - java中带有规范模式的存储库模式

java - JavaFx 中的表设计

Java:拆箱整数时出现空指针异常?