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