更改类的包名后,无法反序列化Java对象。我能做些什么呢?

时间:2012-05-15 16:05:52

标签: java serialization deserialization

正如我们所知,当我反序列化一个序列化的Java对象树时,树中的所有类都必须在类路径上。因此,由于有人将某些类移动到另一个包中,因此反序列化会抛出ClassNotFoundException。

我的问题是,有没有比实现我自己的序列化/反序列化更简单的解决方法?

2 个答案:

答案 0 :(得分:6)

好的,我意识到这个问题可能是重复的。 Stephen's answer to a previous post对我很有用,我可以反序化那些被移到另一个包中的类。为了记录,我在这里放了我使用的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;
    }

}

答案 1 :(得分:1)

我认为关于更改类描述符的link provided above by Stephen C可能是最好的。我希望几个月前我必须实现类似的东西。

虽然我不确定它会起作用,因为在我的情况下,原来的类已经发展得如此之多以至于它们不再反映原始结构,因此它需要在幕后使用大量的木工才能使其工作

无论如何,最近我不得不解决类似的问题。在我的例子中,我创建了一个迁移器类。在其中我使用seconday类加载器加载我的类的旧版本(原始包中的那些),并使用它们我提取序列化对象中的信息,然后将其复制到它们的新版本(新版本中的那些)包装结构)。不幸的是,由于我使用了两个独立的类加载器,因此在没有一定量的Java反射的情况下无法完成复制。