-
Bug
-
Resolution: Fixed
-
P3
-
1.4.0, 1.4.2, 1.4.2_01
-
b07
-
x86
-
linux
-
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 :
When emitting statements, the XMLEncoder does not correctly emit an idref for a given object A if A is the target of the Expression to produce B, A is an argument to that Expressiona of, and B is encountered before A.
a
The problem is in outputStatement(Statement p_stmt, Object outer, boolean isArgument)
There is an if block:
if (outer == target) {
...
}
else if (...) {
...
}
else if (...) {
...
}
else {
d.refs = 2;
outputValue(target, outer, false);
outputValue(value, outer, false);
return;
}
When emitting the target, it has not seen another reference to target, so the code in outputStatement() that sets ValueData.name in the target's ValueData is not encountered. Since ValueData.name is never set, it tries to write the Expression for target when writing the arguments for B. Then, the target is written, but since the value is in the statement list of the target, it writes the value again, which writes the target because target is an argument of the value's Expression, ad infinitum.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac PT1.java
java PT1
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void id="PT1$A0" class="PT1$A">
<void id="PT1$B0" method="newB">
<object idref="PT1$A0"/>
</void>
</void>
</java>
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
...
(infinite recursion)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.io.*;
class PT1
{
public static void main(String[] argv)
throws Exception
{
XMLEncoder encoder = new XMLEncoder(System.out);
encoder.setExceptionListener(new ExceptionListener()
{ public void
exceptionThrown(Exception e)
{ e.printStackTrace(); }
});
encoder.setPersistenceDelegate(B.class, new BDelegate());
A a = new A();
B b = a.newB(a);
encoder.writeObject(b);
encoder.close();
}
public static class A
{
public A()
{}
public B newB(A a)
{ return new B(a); }
}
public static class B
{
private final A m_a;
public B(A a)
{ m_a = a; }
public A getA()
{ return m_a; }
}
public static class BDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
B b = (B)p_old;
A a = b.getA();
return new Expression(b, a, "newB", new Object[] { a });
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If you increment the reference count to target in the else block referred to in the detailed description, as follows:
else {
d.refs = 2;
/*NEW*/getValueData(target).refs++;
outputValue(target, outer, false);
outputValue(value, outer, false);
return;
}
this fixes this problem.
(Incident Review ID: 245032)
======================================================================
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 :
When emitting statements, the XMLEncoder does not correctly emit an idref for a given object A if A is the target of the Expression to produce B, A is an argument to that Expressiona of, and B is encountered before A.
a
The problem is in outputStatement(Statement p_stmt, Object outer, boolean isArgument)
There is an if block:
if (outer == target) {
...
}
else if (...) {
...
}
else if (...) {
...
}
else {
d.refs = 2;
outputValue(target, outer, false);
outputValue(value, outer, false);
return;
}
When emitting the target, it has not seen another reference to target, so the code in outputStatement() that sets ValueData.name in the target's ValueData is not encountered. Since ValueData.name is never set, it tries to write the Expression for target when writing the arguments for B. Then, the target is written, but since the value is in the statement list of the target, it writes the value again, which writes the target because target is an argument of the value's Expression, ad infinitum.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac PT1.java
java PT1
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void id="PT1$A0" class="PT1$A">
<void id="PT1$B0" method="newB">
<object idref="PT1$A0"/>
</void>
</void>
</java>
ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2_04" class="java.beans.XMLDecoder">
<void class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
<void id="PT1$B0" method="newB">
<object class="PT1$A">
...
(infinite recursion)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.beans.*;
import java.io.*;
class PT1
{
public static void main(String[] argv)
throws Exception
{
XMLEncoder encoder = new XMLEncoder(System.out);
encoder.setExceptionListener(new ExceptionListener()
{ public void
exceptionThrown(Exception e)
{ e.printStackTrace(); }
});
encoder.setPersistenceDelegate(B.class, new BDelegate());
A a = new A();
B b = a.newB(a);
encoder.writeObject(b);
encoder.close();
}
public static class A
{
public A()
{}
public B newB(A a)
{ return new B(a); }
}
public static class B
{
private final A m_a;
public B(A a)
{ m_a = a; }
public A getA()
{ return m_a; }
}
public static class BDelegate
extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object p_old, Encoder p_out)
{
B b = (B)p_old;
A a = b.getA();
return new Expression(b, a, "newB", new Object[] { a });
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If you increment the reference count to target in the else block referred to in the detailed description, as follows:
else {
d.refs = 2;
/*NEW*/getValueData(target).refs++;
outputValue(target, outer, false);
outputValue(value, outer, false);
return;
}
this fixes this problem.
(Incident Review ID: 245032)
======================================================================
- duplicates
-
JDK-4936682 LTP: XMLEncoder does not create references to the targets of Expressions
- Closed
- relates to
-
JDK-5023559 LTP: XMLEncoder emits an extraneous reference to an object with nested targets
- Closed
-
JDK-6582164 JavaBeans tests should be open source
- Resolved