让 Java 运行时忽略 serialVersionUIDs? [英] Make Java runtime ignore serialVersionUIDs?

查看:21
本文介绍了让 Java 运行时忽略 serialVersionUIDs?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须处理大量未明确指定 serialVersionUID 的已编译 Java 类.因为它们的 UID 是由编译器任意生成的,许多需要序列化和反序列化的类最终会导致异常,即使实际的类定义匹配.(当然,这都是预期的行为.)

I have to work with a large number of compiled Java classes which didn't explicitly specify a serialVersionUID. Because their UIDs were arbitrarily generated by the compiler, many of the classes which need to be serialized and deserialized end up causing exceptions, even though the actual class definitions match up. (This is all expected behavior, of course.)

返回并修复所有这些 3rd 方代码对我来说是不切实际的.

It is impractical for me to go back and fix all of this 3rd-party code.

因此,我的问题是:有什么方法可以让 Java 运行时忽略serialVersionUID 的差异,并且只有在结构上存在实际差异时才能反序列化?

Therefore, my question is: Is there any way to make the Java runtime ignore differences in serialVersionUIDs, and only fail to deserialize when there are actual differences in structure?

推荐答案

如果您可以访问代码库,则可以使用 Ant 的SerialVer 任务 在可序列化类的源代码中插入和修改serialVersionUID 并一劳永逸地解决问题.

If you have access to the code base, you could use the SerialVer task for Ant to insert and to modify the serialVersionUID in the source code of a serializable class and fix the problem once for all.

如果你不能,或者如果这不是一个选项(例如,如果你已经序列化了一些你需要反序列化的对象),一个解决方案是扩展 ObjectInputStream.增强其行为以将流描述符的 serialVersionUID 与该描述符所代表的本地 JVM 中类的 serialVersionUID 进行比较,并在不匹配的情况下使用本地类描述符.然后,只需使用此自定义类进行反序列化.像这样的东西(归功于这条消息):

If you can't, or if this is not an option (e.g. if you have already serialized some objects that you need to deserialize), one solution would be to extend ObjectInputStream. Augment its behavior to compare the serialVersionUID of the stream descriptor with the serialVersionUID of the class in the local JVM that this descriptor represents and to use the local class descriptor in case of mismatch. Then, just use this custom class for the deserialization. Something like this (credits to this message):

import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DecompressibleInputStream extends ObjectInputStream {

    private static Logger logger = LoggerFactory.getLogger(DecompressibleInputStream.class);
    
    public DecompressibleInputStream(InputStream in) throws IOException {
        super(in);
    }
    
    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
        Class localClass; // the class in the local JVM that this descriptor represents.
        try {
            localClass = Class.forName(resultClassDescriptor.getName()); 
        } catch (ClassNotFoundException e) {
            logger.error("No local class for " + resultClassDescriptor.getName(), e);
            return resultClassDescriptor;
        }
        ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
        if (localClassDescriptor != null) { // only if class implements serializable
            final long localSUID = localClassDescriptor.getSerialVersionUID();
            final long streamSUID = resultClassDescriptor.getSerialVersionUID();
            if (streamSUID != localSUID) { // check for serialVersionUID mismatch.
                final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");
                s.append("local serialVersionUID = ").append(localSUID);
                s.append(" stream serialVersionUID = ").append(streamSUID);
                Exception e = new InvalidClassException(s.toString());
                logger.error("Potentially Fatal Deserialization Operation.", e);
                resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization
            }
        }
        return resultClassDescriptor;
    }
}

这篇关于让 Java 运行时忽略 serialVersionUIDs?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆