当前位置: 首页 > 面试题库 >

使Java运行时忽略serialVersionUID?

袁阿苏
2023-03-14
问题内容

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

对我来说,返回并修复所有第3方代码是不切实际的。

因此,我的问题是:是否有任何方法可以使Java运行时 忽略 serialVersionUID中的差异,并且仅在结构上存在实际差异时才无法反序列化?


问题答案:

如果您有权访问代码库,则可以使用Ant的SerialVer任务来插入和修改serialVersionUID可序列化类的源代码,并彻底解决此问题。

如果不能这样做,或者这不是一个选择(例如,如果您已经序列化了一些需要反序列化的对象),则一种解决方案是extend
ObjectInputStream。增强其行为,以比较serialVersionUID流描述符与serialVersionUID该描述符表示的本地JVM中的类的类,并在不匹配的情况下使用本地类描述符。然后,只需使用此自定义类进行反序列化即可。这样的东西(此消息的信用):

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;
    }
}


 类似资料:
  • 我们有一个Spring-Boot1.0.rc1应用程序,为日志配置了logback,并在src/test/resources中有一个logback.xml文件。当我们从maven运行spring-boot时,日志文件似乎会被看到和尊重。(这是我们在spring-boot徽标之后所需的日志格式) 但是,当我们删除一个溜进src/java/resources的流氓logback.xml文件,并在其他所

  • 我正在Scala中开发一个利用SBT构建的Spark应用程序。Spark创建了非常冗长的日志记录,在运行测试时,我希望忽略这些日志记录。 我在src/test/resources和src/main/resources下设置了log4j.properties文件,其内容如下:

  • 问题内容: 在这个例子中 如果JSON对象缺少属性“ age”, 有人说它不能反序列化。在反序列化期间是否有 注释 可以忽略丢失的字段? 谢谢 问题答案: 我想你想要的是 这就是Jackson 1.x的方式。我认为2.x中有一种新方法。就像是 这些将告诉Jackson仅序列化不为null的值,并且在反序列化缺少的值时不会抱怨。我认为它将只是将其设置为Java默认值。

  • 我正在使用计划执行服务 以固定速率运行runnable

  • 有什么办法能做到这一点吗? 谢谢!

  • 我使用的是PACT JVM https://github.com/dius/pact-jvm/tree/master/provider/pact-jvm-provider-junit我不知道为什么我的联系人中的匹配规则被忽略了。我的HTTP测试 还有我的合同档案 并在运行后显示错误 请帮忙把我的观点说错。 谢谢,