众所周知,当我反序列化一个序列化的 Java 对象树时,树中的所有类都必须在类路径中。因此,由于有人将一些类移动到另一个包中,反序列化会抛出 ClassNotFoundException。
我的问题是,有没有比实现我自己的序列化/反序列化更简单的方法来解决这个问题?
众所周知,当我反序列化一个序列化的 Java 对象树时,树中的所有类都必须在类路径中。因此,由于有人将一些类移动到另一个包中,反序列化会抛出 ClassNotFoundException。
我的问题是,有没有比实现我自己的序列化/反序列化更简单的方法来解决这个问题?
好的,我意识到这个问题可能是重复的。斯蒂芬对上一篇文章的回答对我来说很好,我可以反序列化那些被移动到另一个包的类。为了记录,我把我使用的 ObjectInputStream 的子类放在这里。
public class ClassNameMappingObjectInputStream extends ObjectInputStream {
public static Map<String, Class> classNameMapping = initclassNameMapping();
private static Map<String, Class> initclassNameMapping(){
Map<String, Class> res = new HashMap<String, Class>();
res.put("com.lsy.nlm.report.filter.Filter", com.lsy.nlm.filter.Filter.class);
res.put("com.lsy.nlm.report.filter.FilterSummary", com.lsy.nlm.filter.FilterSummary.class);
res.put("com.lsy.nlm.report.filter.TopFilter", com.lsy.nlm.filter.TopFilter.class);
return Collections.unmodifiableMap(res);
}
public ClassNameMappingObjectInputStream(InputStream in) throws IOException {
super(in);
}
protected ClassNameMappingObjectInputStream() throws IOException, SecurityException {
super();
}
@Override
protected java.io.ObjectStreamClass readClassDescriptor()
throws IOException, ClassNotFoundException {
ObjectStreamClass desc = super.readClassDescriptor();
if (classNameMapping.containsKey(desc.getName())){
return ObjectStreamClass.lookup(classNameMapping.get(desc.getName()));
}
return desc;
}
}
我认为Stephen C 上面提供的关于更改类描述符的链接可能是最好的。我希望我在几个月前必须实施类似的事情时就知道这一点。
虽然我不确定它是否会起作用,因为在我的情况下,原始类已经发展得如此之多,以至于它们不再反映原始结构,因此它需要在幕后进行大量木工才能使其工作。
无论如何,最近我不得不解决一个类似的问题。就我而言,我创建了一个迁移器类。在其中,我使用 seconday 类加载器来加载我的类的旧版本(原始包中的那些),并用它们提取序列化对象中的信息,然后将其复制到它们的新版本中(新版本中的那些)包结构)。不幸的是,如果没有一定数量的 Java 反射,这种复制就无法完成,因为我正在使用两个单独的类加载器。