Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5023559

LTP: XMLEncoder emits an extraneous reference to an object with nested targets

XMLWordPrintable

    • 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)
      ======================================================================

            malenkov Sergey Malenkov (Inactive)
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: