Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added the code examples

...

This means that to serialize a network of objects containing circular references and then to successfully deserialize the same network the writeUnshared()/readUnshared() methods must not be used.

Consider the following code example.

Code Block
public class Person {

    private String name;
    
    Person() {
        // do nothing - needed for serialization
    }
    
    Person(String theName) {
        name = theName;
    }
    
    public String getName () {
        return name;
    }

// other details not relevant to this example

}

public class Student extends Person implements Serializable {

    private Professor tutor;
    
    Student(){
        // do nothing - needed for serialization
    }
    
    Student(String theName, Professor theTutor) {
        super(theName);
        tutor = theTutor;
    }
    
    public Professor getTutor() {
        return tutor;
    }
}

public class Professor extends Person implements Serializable {
    
    private ArrayList<Student> tutees = new ArrayList<Student>();
    
    Professor(){
        // do nothing - needed for serialization
    }
    
    Professor(String theName) {
        super(theName);
    }
    
    public ArrayList<Student> getTutees () {
        return tutees;
    }
    
    /*
     * checkTutees checks that all the tutees
     * have this Professor as their tutor
     */
    public boolean checkTutees () {
        boolean result = true;
        for(Student stu: tutees) {
            if (stu.getTutor() != this) {
                result = false;
                break;
            }
        }
        return result;
    }
}

// ...

Professor jane = new Professor("Jane");
        
Student able = new Student("Able", jane);
Student baker = new Student("Baker", jane);
Student charlie = new Student("Charlie", jane);
        
jane.getTutees().add(able);
jane.getTutees().add(baker);
jane.getTutees().add(charlie);
        
System.out.println("checkTutees returns: " + jane.checkTutees());
// prints "checkTutees returns: true"

Professor and Students are types that extend the basic type Person.  A student (i.e., an object of type Student) has a tutor of type Professor.  A professor (i.e., an object of type Professor) has a list (actually, an ArrayList) of tutees (of type Student).  The method checkTutees() checks whether all of the tutees of this professor have this professor as their tutor, returning true if that is the case and false otherwise.  We then create Professor Jane who has three tutees, Able, Baker, and Charlie, all of whom have Professor Jane as their tutor.  The println() statement prints true.

Noncompliant Code Example

This noncompliant code example does something bad attempts to serialize the data from the example above using writeUnshared().  However, when the data is deserialized using readUnshared(), the checkTutees() method no longer returns true because the tutor objects of the three students are different objects from the original Professor object.

Code Block
bgColor#FFcccc
String filename = "serial";

 try {
    System.out.println("Serializing using writeUnshared");
    ObjectOutputStream oos = new ObjectOutputStream
        (new FileOutputStream(filename));
            
    oos.writeUnshared(jane);
    oos.close();
            
    System.out.println("Deserializing using readUnshared");
    ObjectInputStream ois = new ObjectInputStream
        (new FileInputStream(filename));
            
    Professor jane2 = (Professor)ois.readUnshared();
    ois.close();
            
    System.out.println("checkTutees returns: " +
        jane3.checkTutees());
    // need some code here
 prints "checkTutees returns: false"
            
} catch(Exception e) {
    System.out.println("Exception during deserialization" + e);
}

Compliant Solution

This compliant solution overcomes the problem of the noncompliant code example by using writeObject() and readObject(), ensuring that the tutor objects of the three students are the same as the original Professor object.

Code Block
bgColor#ccccff
String filename = "serial";

try {
    System.out.println("Serializing using writeObject");
    ObjectOutputStream oos = new ObjectOutputStream
        (new FileOutputStream(filename));
            
    oos.writeObject(jane);
    oos.close();
            
    System.out.println("Deserializing using readObject");
    ObjectInputStream ois = new ObjectInputStream
        (new FileInputStream(filename));
            
    Professor jane2 = (Professor)ois.readObject();
    ois.close();
            
    System.out.println("checkTutees returns: " +
        jane2.checkTutees());
    // need some code here prints "checkTutees returns: true"
            
} catch(Exception e) {
    System.out.println("Exception during deserialization" + e);
}

Risk Assessment

Using the writeUnshared() and readUnshared() methods may produce unexpected results.

...