1

In my TCP server-client implementation, all of my packets are derived from an abstract base class that implements Serializable. I am converting the class into bytes and send it through the socket, and receiver takes these bytes to deserialize and successfully receive the packet. Because of my lack of knowledge about serialization, I am not sure if this will work because every packet class has a warning like that:

The serializable class CreateObjectPacket does not declare a static final serialVersionUID field of type long

After a bit research, I have found out that JVM uses this UID to ensure the deserialization will be successful (if i am not wrong), so in order to get rid of this warning, i let the eclipse generate default UID but even though Client and Server program have exactly same classes about Packets, the UIDs are different on same classes. Will it cause any problems upon deserialization or should i manually set these UIDs like 1,2,3... ? By the way, I am deserializing the incoming bytes into the super abstract class, Packets, is it also a problem or should i feel free to cast this into the derived Packets ?

EDIT: Lastly, my abstract Packets class has a static methods called fromByteArray for deserialization :

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;
}
deniz
  • 2,427
  • 4
  • 27
  • 38

1 Answers1

1

After a bit research, I have found out that JVM uses this UID to ensure the deserialization will be successful

Specifically, it is used to identify the version of the object being (de)serialized. When you allow the UID to be assigned automatically, your development environment (IDE) is supposed to assign a new UID if the internal structure of the object to be serialized happens to change. This allows the JVM to recognize if you attempt to de-serialize one version of an object into a different version of an object with the same class name.

If you assign the version ID yourself and change the internal structure (i.e. member fields) of the object, you are also expected to change the version ID. This is so the JVM will be able to catch when you have a version mismatch between your class definition and the object you are trying to deserialize from disk/network.

re comments: http://docs.oracle.com/javase/6/docs/platform/serialization/spec/version.html 5.6 Type Changes Affecting Serialization - Compatible vs. Incompatible changes

The purpose of the UID is to indicate to the JVM whether or not the serialized structure of the object has changed in a way that no part of the object can be reliably deserialized. As I wrote above, it is only supposed to change when incompatible changes are made to the structure of the object being serialized. If the object is identical on both the client and the server, you will probably have trouble deserializing the object if the UIDs don't match between the client code and the server code. You can get around this by not defining the UID, but be aware of the consequences should your object implementation change in the future.

user1445967
  • 1,520
  • 4
  • 14
  • 30
  • why does it calculate different UIDs for completely same classes ? – deniz May 07 '13 at 21:48
  • If we are talking about one person coding on one IDE, it should not calculate a different UID unless you change the member fields of the class. Theoretically, if the member fields are the same, and in the same order, then the serialized form of the object should be the same, and the IDE **should** not change the UID. – user1445967 May 07 '13 at 21:55
  • You aren't 'expected to change the version ID'. This is urban myth. You are expected *not* to change the UID, unless you have a very good reason to introduce a backward incompatibility with all existing serializations, which is vanishingly rare. If you introduce a serialization-incompatibility into the class, which is also rather more difficult than commonly imagined (see the Object Versioning chapter of the Object Serialization Specification), you are expected to take one of the many available measures to preserve stream compatibility. – user207421 May 07 '13 at 21:56
  • I believe I stated the conditions for changing the UID that 1) you assigned the UID yourself in the first place and 2) you changed the internal structure of the object. – user1445967 May 07 '13 at 22:03
  • So? It is still incorrect to state that 'you are expected to change the version ID'. You aren't. It is a major mistake to do so, and it is a major mistake to tell people to do so. This is urban myth. You wont find any normative references that say so, and there is a Sun paper somewhere that says exactly the opposite: I'll try to find it. – user207421 May 07 '13 at 22:14
  • I have just tried, it worked but id of the packet is always 0, i dont know why. ID is defined in abstract Packets class as protected byte, everything except ID is correct when i deserialize. – deniz May 07 '13 at 22:18
  • You haven't deployed your new code correctly to the deserializing end. – user207421 May 07 '13 at 22:22
  • oh Packets.java was not in the same package, okay everything works now, lol. – deniz May 07 '13 at 22:23