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

LTP: XMLEncoder does not update ref count on Statement target in outputStatement()

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 1.4.0, 1.4.2, 1.4.2_01
    • Fix Version/s: 7
    • Component/s: client-libs
    • Subcomponent:
    • Resolved In Build:
      b07
    • CPU:
      x86
    • OS:
      linux
    • Verification:
      Verified

      Description

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

        Attachments

          Issue Links

            Activity

              People

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

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: