-
Bug
-
Resolution: Fixed
-
P3
-
1.4.2, 5.0
-
b15
-
x86
-
linux, windows_2000
-
Verified
Name: jl125535 Date: 03/30/2004
FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS independent
A DESCRIPTION OF THE PROBLEM :
Suppose an object VALUE with a "nontrivial target" (meaning it's instantiate() method returned an Expression describing an instance method on another object) is encountered while the XMLEncoder is attempting to emit XML (i.e., during flush()). Let the target of VALUE be PARENT. If PARENT also has a nontrivial target, called GRANDPARENT, and neither GRANDPARENT nor PARENT have been encountered in the emitting process, an extraneous reference to PARENT will be written to the stream. This is generalizable for as many PARENT objects are "between" VALUE and GRANDPARENT, i.e., if PARENT has a target PARENT1, and PARENT1 has a target PARENT2, ... and PARENTn has the target GRANDPARENT, an extraneous reference will be written for each PARENT, PARENT1...PARENTn.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac PT3.java
java PT3
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT3$A">
<void id="PT3$B0" method="newB">
<void id="PT3$C0" method="newC"/>
</void>
</void>
<object idref="PT3$C0"/>
</java>
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT3$A">
<void id="PT3$B0" method="newB">
<void id="PT3$C0" method="newC"/>
</void>
</void>
<object idref="PT3$B0"/>
<object idref="PT3$C0"/>
</java>
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.io.*;
public class PT3
{
public static void main(String[] argv)
{
XMLEncoder encoder = new XMLEncoder(System.out);
encoder.setPersistenceDelegate(B.class, new BDelegate());
encoder.setPersistenceDelegate(C.class, new CDelegate());
encoder.setExceptionListener(new ExceptionListener()
{
public void
exceptionThrown(Exception e)
{ e.printStackTrace(); }
});
A a = new A();
B b = a.newB();
C c = b.newC();
encoder.writeObject(c);
encoder.close();
}
public static class A
{
public A()
{}
public B newB()
{ return new B(this); }
}
public static class B
{
private final A m_a;
public B(A a)
{ m_a = a; }
public A getA()
{ return m_a; }
public C newC()
{ return new C(this); }
}
public static class C
{
private final B m_b;
public C(B b)
{ m_b = b; }
public B getB()
{ return m_b; }
}
public static class BDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
B b = (B)p_old;
return new Expression(p_old, b.getA(), "newB", new Object[0]);
}
}
public static class CDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
C c = (C)p_old;
return new Expression(p_old, c.getB(), "newC",
new Object[0]);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Add the following block of code in the else block of the if (target == outer) in outputStatement():
else {
d.refs = 2;
outputValue(target, outer, false);
// START NEW BLOCK
if (isArgument) {
outputValue(value, outer, false);
}
// END NEW BLOCK
// OLD outputValue(value, outer, false);
return;
}
and compile the resulting XMLEncoder, put in your bootclasspath.
(Incident Review ID: 245071)
======================================================================
FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS independent
A DESCRIPTION OF THE PROBLEM :
Suppose an object VALUE with a "nontrivial target" (meaning it's instantiate() method returned an Expression describing an instance method on another object) is encountered while the XMLEncoder is attempting to emit XML (i.e., during flush()). Let the target of VALUE be PARENT. If PARENT also has a nontrivial target, called GRANDPARENT, and neither GRANDPARENT nor PARENT have been encountered in the emitting process, an extraneous reference to PARENT will be written to the stream. This is generalizable for as many PARENT objects are "between" VALUE and GRANDPARENT, i.e., if PARENT has a target PARENT1, and PARENT1 has a target PARENT2, ... and PARENTn has the target GRANDPARENT, an extraneous reference will be written for each PARENT, PARENT1...PARENTn.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac PT3.java
java PT3
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT3$A">
<void id="PT3$B0" method="newB">
<void id="PT3$C0" method="newC"/>
</void>
</void>
<object idref="PT3$C0"/>
</java>
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT3$A">
<void id="PT3$B0" method="newB">
<void id="PT3$C0" method="newC"/>
</void>
</void>
<object idref="PT3$B0"/>
<object idref="PT3$C0"/>
</java>
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.io.*;
public class PT3
{
public static void main(String[] argv)
{
XMLEncoder encoder = new XMLEncoder(System.out);
encoder.setPersistenceDelegate(B.class, new BDelegate());
encoder.setPersistenceDelegate(C.class, new CDelegate());
encoder.setExceptionListener(new ExceptionListener()
{
public void
exceptionThrown(Exception e)
{ e.printStackTrace(); }
});
A a = new A();
B b = a.newB();
C c = b.newC();
encoder.writeObject(c);
encoder.close();
}
public static class A
{
public A()
{}
public B newB()
{ return new B(this); }
}
public static class B
{
private final A m_a;
public B(A a)
{ m_a = a; }
public A getA()
{ return m_a; }
public C newC()
{ return new C(this); }
}
public static class C
{
private final B m_b;
public C(B b)
{ m_b = b; }
public B getB()
{ return m_b; }
}
public static class BDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
B b = (B)p_old;
return new Expression(p_old, b.getA(), "newB", new Object[0]);
}
}
public static class CDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
C c = (C)p_old;
return new Expression(p_old, c.getB(), "newC",
new Object[0]);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Add the following block of code in the else block of the if (target == outer) in outputStatement():
else {
d.refs = 2;
outputValue(target, outer, false);
// START NEW BLOCK
if (isArgument) {
outputValue(value, outer, false);
}
// END NEW BLOCK
// OLD outputValue(value, outer, false);
return;
}
and compile the resulting XMLEncoder, put in your bootclasspath.
(Incident Review ID: 245071)
======================================================================
- duplicates
-
JDK-6187118 LTP: XMLEncoder creates valid but wrong archives for immutable objects
- Closed
- relates to
-
JDK-7169395 Exception throws due to the changes in JDK 7 object tranversal and break backward compatibility
- Resolved
-
JDK-5023552 LTP: XMLEncoder does not update ref count on Statement target in outputStatement()
- Closed
-
JDK-6582164 JavaBeans tests should be open source
- Resolved