【发布时间】:2019-10-05 22:13:10
【问题描述】:
前段时间我发布了一个序列化/反序列化用户对象的应用程序。
public String serializeUser(final User user) {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(user);
objectOutputStream.close();
} catch (final IOException exception) {
...
}
return new String(Base64.encode(byteArrayOutputStream.toByteArray(), DEFAULT));
}
public User deserializeString(final String userString) {
final byte userBytes[] = Base64.decode(userString.getBytes(), DEFAULT);
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(userBytes);
final ObjectInputStream objectInputStream;
final User user;
try {
objectInputStream = new ObjectInputStream(byteArrayInputStream);
user = (User) objectInputStream.readObject();
objectInputStream.close();
} catch (final IOException | ClassNotFoundException exception) {
...
}
return user;
}
对象是这样实现的:
public class User implements Serializable {
private String email;
private String name;
...
}
然后,在修改我的对象(我添加了一个新字段)之后,我学到了一个艰难的方法,即必须设置 serialVersionUID 以防对象定义发生变化,否则反序列化器将无法识别存储对象(因为它会自动生成serialVersionUID)。所以我继续这样做:
public class User implements Serializable {
private static final long serialVersionUID = 123L;
...
}
但是现在我已经重新发布了带有这些更改的应用程序,我不断收到错误报告,指出无法反序列化对象:
原因:java.io.InvalidClassException: com.myproject.h.e;本地类不兼容:stream classdesc serialVersionUID = 184861231695454120,本地类serialVersionUID = -2021388307940757454
我非常清楚,设置新的串行版本会使任何以前的串行版本(link1、link2)失效,但事实并非如此。如您所见,错误日志指向的 serialVersionUID(18486... 和 -20213...)与我手动设置为 User 类(123L)的完全不同。
我错过了什么?
如果有任何相关性,我将使用 Proguard 和默认配置。
【问题讨论】:
-
(FWIW,如果你在JDK中使用
serialver命令行程序,它会给你一个类的序列版本UID。即使你没有指定具体的值,Java序列化机制将为您计算一个。使用相同的 UID 可以读取旧数据。尽管如果您发布了多个版本,但公共方法略有不同(请参阅文档了解详细信息),那么它们将产生不兼容的数据。)跨度>
标签: java android deserialization proguard serialversionuid