Name: gm110360 Date: 10/13/2003
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-39)
Java HotSpot(TM) Client VM (build 1.4.1_01-14, mixed mode)
A DESCRIPTION OF THE PROBLEM :
XMLEncoder is supposed to use id and idref attributes to ensure that a given object is only serialized once, even if it occurs multiple times in the set of objects being written. It fails to do this, however, when an object appears as the target of an Expression. Instead, it creates multiple distinct objects.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
This is demonstrated by the program below. It defines the classes A and B, where B is an inner class of A. B's constructor is private, so it cannot be instantiated directly. Instead, every instance of A has an internal instance of B which is created at the same time. Therefore, the PersistanceDelegate for B "instantiates" an object by calling getB() on its A.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In the output from the program, notice that two different instances of A are created: one to serve as the target of the getB() method, and a second one as the second element of the array. This is incorrect. In the original array which was serialized, both of these were the same object. The encoder should have used an idref attribute to create two references to the same object.
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.1_01" class="java.beans.XMLDecoder">
<array class="java.lang.Object" length="2">
<void index="0">
<void class="A">
<void id="A$B0" property="b"/>
</void>
<object idref="A$B0"/>
</void>
<void index="1">
<object class="A">
<void id="A$B0" property="b"/>
</object>
</void>
</array>
</java>
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
public class A
{
private B b;
public A()
{
b = new B();
}
public B getB()
{
return b;
}
public class B
{
private B()
{
}
public A getA()
{
return A.this;
}
}
public static class BDelegate extends DefaultPersistenceDelegate
{
public BDelegate()
{
}
protected Expression instantiate(Object oldInstance, Encoder out)
{
B oldB = (B) oldInstance;
A oldA = oldB.getA();
return new Expression(oldB, oldA, "getB", new Object [0]);
}
}
public static void main(String args[])
{
XMLEncoder enc = new XMLEncoder(System.out);
enc.setPersistenceDelegate(B.class, new BDelegate());
A a = new A();
enc.writeObject(new Object [] {a.getB(), a});
enc.close();
}
}
---------- END SOURCE ----------
(Incident Review ID: 189243)
======================================================================