序列化:serialVersionUID在网络上的重要性

时间:2013-05-07 21:26:20

标签: java networking serialization

在我的TCP服务器 - 客户端实现中,我的所有数据包都是从实现Serializable的抽象基类派生的。我正在将类转换为字节并通过套接字发送,接收器将这些字节反序列化并成功接收数据包。由于我对序列化缺乏了解,我不确定这是否有效,因为每个数据包类都有这样的警告:

  

可序列化类CreateObjectPacket未声明long类型的静态最终serialVersionUID字段

经过一番研究后,我发现JVM使用这个UID来确保反序列化成功(如果我没有错),所以为了摆脱这个警告,我让eclipse生成默认的UID但是尽管客户端和服务器程序具有完全相同的关于数据包的类,但是相同类的UID是不同的。它会在反序列化时引起任何问题,还是应该手动设置这些UID,如1,2,3 ......?顺便说一句,我将传入的字节反序列化为超级抽象类Packets,这也是一个问题,还是我可以随意将其转换为派生的数据包?

编辑:最后,我的抽象Packets类有一个名为fromByteArray的静态方法用于反序列化:

public static Packets fromByteArray(byte[] arr) {

    ByteArrayInputStream bis = new ByteArrayInputStream(arr);
    ObjectInput in = null;
    try {
        in = new ObjectInputStream(bis);
        Packets o = (Packets) in.readObject();
        return o;
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            bis.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    return null;
}

1 个答案:

答案 0 :(得分:1)

经过一番研究,我发现JVM使用这个UID来确保反序列化成功

具体来说,它用于识别被(de)序列化的对象的版本。当您允许自动分配UID时,如果要序列化的对象的内部结构发生更改,则您的开发环境(IDE)应该分配新的UID。这允许JVM识别您是否尝试将一个版本的对象反序列化为具有相同类名的对象的不同版本。

如果您自己分配版本ID并更改对象的内部结构(即成员字段),则还需要更改版本ID。当您的类定义与您尝试从磁盘/网络反序列化的对象之间存在版本不匹配时,JVM将能够捕获这些内容。

评论: http://docs.oracle.com/javase/6/docs/platform/serialization/spec/version.html 5.6类型更改影响序列化 - 兼容与不兼容的更改

UID的目的是向JVM指示对象的序列化结构是否已经改变,使得对象的任何部分都不能被可靠地反序列化。正如我在上面所写的那样,只有在对被序列化对象的结构进行不兼容的更改时,才应该更改它。 如果客户端和服务器上的对象相同,如果客户端代码和服务器代码之间的UID不匹配,则可能无法反序列化对象。您可以通过以下方式解决此问题。没有定义UID,但要注意将来对象实现发生变化的后果。