Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
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) ======================================================================
|