Mridul Vishal
Mridul Vishal

Reputation: 2310

serialization/deserialization mechanism

Say, I have a class X which has a field value, that is,

class X implements Serializable {
    private int value;
    // ...
}

Further it has getters and setters not displayed here. This class is serialized. At the deserialzation, end same class has value field and access specifier is public. Further, this class does not have getters and setters. So, my questions are:

  1. Does deserialization fail in case the access specifier of the field changes OR some or all of the methods go missing in the class at the deserialization end?
  2. What is the mechanism by which fields are assigned their values during deserialization?

Upvotes: 5

Views: 21700

Answers (5)

user207421
user207421

Reputation: 310840

Does deserialization fail in case the access specifier of the field changes

No.

OR some or all of the methods go missing in the class at the deserialization end?

Yes, unless the receiving class has a serialVersionUID member whose value equals the value encoded in the stream.

what is the mechanism by which fields are assigned their values during deserialization?

Too broad, but:

  • Reflection, and
  • name matching (rather than matching by position in the class and stream).

Upvotes: 0

Martijn Courteaux
Martijn Courteaux

Reputation: 68847

I don't really know how you get this results, but what you tell is not the default behaviour of serialisation. So, I guess you are using it wrong. Here is some sample code:

public class X implements Serializable
{
     private int value;

     public int getValue() { return value; }
}

Here the serialisation/deserialisation process:

X x = new X();
x.setValue(4);

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputSteam(buffer);
oos.writeObject(x);
oos.flush();
oos.close();

ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
ObjectInputStream ois = new ObjectInputStream(in);
Object obj = ois.readObject();
if (obj instanceof X)
{
    X readObject = (X) obj;
    System.out.println(readObject.getValue());
}

You probably used Java Reflection to get your results. Make sure you use getDeclaredFields(); and getDeclaredMethods(); instead of the variants without Declared in the method name.

Upvotes: 2

Dead Programmer
Dead Programmer

Reputation: 12575

Some good links The Java serialization algorithm revealed

1) does deserialization fail in case the access specifier of the field changes OR some or all of the methods go missing in the class at the deserialization end ?

Serialization happens using Using Reflection

Java Detects the changes to a class using the

private static final long serialVersionUID

The default involves a hashcode. Serialization creates a single hashcode, of type long, from the following information:

  • The class name and modifiers

  • The names of any interfaces the class implements

  • Descriptions of all methods and constructors except private methods and constructors

  • Descriptions of all fields except private, static, and private transient

The default behavior for the serialization mechanism is a classic "better safe than sorry" strategy. The serialization mechanism uses the suid, which defaults to an extremely sensitive index, to tell when a class has changed. If so, the serialization mechanism refuses to create instances of the new class using data that was serialized with the old classes.

2) what is the mechanism by which fields are assigned their values during deserialization ?

Upvotes: 5

JBert
JBert

Reputation: 3390

The real details can be read in the Java Object Serialization Specification.

To answer your questions:

  1. Serialization has a basic sanity check to see if the serialization ends use the same version of a class: the serialVersionUID member must be equal. Read the section Stream Unique Identifiers to know more about it. Basically, it's a static value which you can either manage yourself by declaring it on your class, or let the compiler generate one for you. If the compiler generates it, ANY change to a class will result in a change of serialVersionUID and hence will make the deserialization fail if the ends do not have exactly the same classes. If you want to avoid this, declare the variable yourself and update it manually when a change to the class' member variables does make classes incompatible.

  2. The Java Virtual Machine does a lot of the magic here, it can access all internal state directly without the need for getters (fields marked transient or static aren't serialized though). Also, while the Serializable interface doesn't specify any methods to implement, there are a number of 'magic methods' which you can declare to influence the serialization process. Read section "The writeObject Method" and onwards to know more. Be aware though that you should use these sparingly as they might confuse any maintenance developers!

Upvotes: 3

dbf
dbf

Reputation: 6499

You don't need to have getters/setter to serialize/deserialize using java serialization, for example, check this code:

public class Main {

    public static class Q implements Serializable {
        private int x;
        public Q() {
            x = 10;
        }
        public void printValue() {
            System.out.println(x);
        }
    }

    public static void main(String[] args) throws Exception {
        Q q = new Q();
        FileOutputStream fos = new FileOutputStream("c:\\temp.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(q);
        fos.close();

        FileInputStream fis = new FileInputStream("c:\\temp.out");
        ObjectInputStream oin = new ObjectInputStream(fis);
        Q q2 = (Q)oin.readObject();
        fis.close();
        q2.printValue();

    }
}

Upvotes: 2

Related Questions