二进制数据的Java序列化期间出现InvalidClassException

二进制数据的Java序列化期间出现InvalidClassException,java,serialization,udp,deserialization,Java,Serialization,Udp,Deserialization,在我的实现中,我使用Java序列化跨一组二进制对象发送消息,从通知头开始,通知头告诉将要传递多少个对象以及它们各自的大小。仅仅从简单的测试开始,我就能够成功地传输header对象,然后我尝试只发送一个1024字节的数据对象。但是,运行测试后,我观察到以下情况: 第一个数据对象正在成功传递,并且也被接收 当我发送第二个对象时,我看到来自第一个对象的一些数据仍然作为第二个数据集的前缀出现;导致第二个对象的截断和InvalidClassException 有人能提供一些关于这个问题是什么以及如何解

在我的实现中,我使用Java序列化跨一组二进制对象发送消息,从通知头开始,通知头告诉将要传递多少个对象以及它们各自的大小。仅仅从简单的测试开始,我就能够成功地传输header对象,然后我尝试只发送一个1024字节的数据对象。但是,运行测试后,我观察到以下情况:

  • 第一个数据对象正在成功传递,并且也被接收
  • 当我发送第二个对象时,我看到来自第一个对象的一些数据仍然作为第二个数据集的前缀出现;导致第二个对象的截断和
    InvalidClassException
有人能提供一些关于这个问题是什么以及如何解决这个问题的建议吗

receiver thread run()方法如下所示

public void run() {

    while (mRunning) {
        try {

            // Receive the serialized object
            byte[] buf = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            System.out.println("SERVER: data received: ");

            // Display the serialized object. 
            byte[] data = packet.getData();
            System.out.println(Arrays.toString(data));

            ByteArrayInputStream in = new ByteArrayInputStream(data);
            ObjectInputStream is = new ObjectInputStream(in);
            try {
                Object obj = is.readObject();
                if (obj instanceof DatakNotification) {
                    System.out.println("Data notification received: ");
                } else if (obj instanceof DataChunk) {
                    System.out.println("Data Chunk received: ");
                }
                System.out.println(obj);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
            mRunning = false;
        }
    }
    socket.close();
}
在日志中,我看到如下内容

第一个对象(标题)

收到阻止通知: 块Id:a5d03647-6434-47bd-ae73-7F95104F71B8块大小:25904块大小:1024最后一个块大小:304总块数:26

第二个对象(1K数据)

服务器:收到的数据: [-84, -19, 0, 5, 115, 114, 0, 39, 99, 111, 109, 46, 99, 111, 110, 97, 46, 118, 105, 100, 101, 111, 99, 108, 105, 101, 11 0, 116, 46, 99, 104, 117, 110, 107, 103, 101, 110, 46, 68, 97, 116, 97, 67, 104, 117, 110, 107, -95, -44, 27, 37, -39, - 34, 12, 17, 2, 0, 5, 73, 0, 7, 109, 76, 101, 110, 103, 116, 104, 90, 0, 7, 109, 77, 97, 114, 107, 101, 100, 73, 0, 12, 1 09, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 91, 0, 4, 109, 66, 117, 102, 116, 0, 2, 91, 66, 76, 0, 8, 109, 6 7, 104, 117, 110, 107, 73, 100, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103 , 59, 120, 112, 0, 0, 4, 0, 0, 0, 0, 0, 0, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, 112, 0 , 0, 4, 0, 70, 76, 86, 1, 1, 0, 0, 0, 9, 0, 0, 0, 0, 18, 0, 0, -73, 0, 0, 0, 0, 0, 0, 0, 2, 0, 10, 111, 110, 77, 101, 11 6, 97, 68, 97, 116, 97, 8, 0, 0, 0, 8, 0, 8, 100, 117, 114, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 119 -124, -7, -22, -22, -62, 86, 12, 1, 45, 29, -126, -128, 24, 6, -48, 96, 3, -53, -15, -95, -24, 48, 31, 1, 10, -4, 24, 7 9、-63、41、68、6]

java.io.InvalidClassException: com.dataxfer.chunkgen.DataChunk; local class incompatible: stream classdesc serialVersionUID = -6785768889157546991, local class serialVersionUID = 2835159210520537273
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:617)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at com.dataxfer.transceiver.LocalUdpReceiver.run(LocalUdpReceiver.java:62)

这意味着编写器和读取器的
serialVersionUID
不匹配。这是因为writer和reader上该类的代码不同

这意味着需要对读取的SerialVersionId进行硬编码以匹配写入程序

尝试设置

private static final long serialVersionUID = -6785768889157546991L;

这仅在您没有更改任何字段的类型或删除任何字段的情况下才有效。

这是您的问题:
stream classdesc serialVersionUID=-6785768889157546991,本地类serialVersionUID=283515921057373
。版本不匹配。是写入程序和读取器的SerialVersionId还是实际数据?我的意思是,我可以从你关于数据本身的论点中看出一点。但为什么读者和作者应该是一样的呢。人们可以用不同的方式实现它们。不是吗?写入程序的SerialVersionId实际上在数据中,读取器检查它的SerialVersionId是否匹配。如果不指定它,它将基于类的字段、构造函数和方法生成。writer的数据结构应该与reader相同,但是如果不重写该字段,java是迂腐的。然而,我得到了另一个例外,而且旧数据对象的前缀仍然存在。我可以通过在两端转储十六进制形式的二进制数据来验证这一点。将异常粘贴到java.io.ObjectInputStream.java.io.EOFEException的java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2744)的java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1344)的java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)的java.io.io.ObjectInputStream(ObjectInputStream.java:1350)在java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)在com.dataxfer.收发器.localudpreciver.run(localudpreciver.java:62)好的..在增加接收器大小的字节缓冲区大小后,我可以纠正这个问题。感谢大家的帮助!
private static final long serialVersionUID = -6785768889157546991L;