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

Exception throws due to the changes in JDK 7 object tranversal and break backward compatibility

    XMLWordPrintable

    Details

    • Subcomponent:
    • Introduced In Version:
      7
    • Resolved In Build:
      b56
    • CPU:
      generic
    • OS:
      generic

      Backports

        Description

        J2SE Version (please include all output from java -version flag):
        7u4


        Does this problem occur on J2SE 6ux or 7ux? Yes / No (pick one)
        No, works fine with 6u32


        Bug Description:

        This issue appears to be due in part to a weird change in ordering in Java 7's object tranversal.

        In Java 6 (note can provide the Java 6 Update 32 version, but it really doesn't change apart from the version number):

            <java version="1.6.0_25" class="java.beans.XMLDecoder">
             <void id="MBeanLoader0" property="owner"/>
             <object id="Emailer0" class="wt.jmx.core.mbeans.Emailer">
              <void id="ArrayList0" property="emailLists">
               <void method="add">
                <object class="wt.jmx.core.mbeans.EmailList">
                 <object idref="Emailer0"/>
                 <string>JMX-Administrators</string>
                 <void property="addressList">
                  <string>###@###.###</string>
                 </void>
                </object>
               </void>
              </void>
              <void property="emailLists">
               <object idref="ArrayList0"/>
              </void>
              <void property="ownerMBean">
               <object idref="MBeanLoader0"/>
              </void>
             </object>
             ...

        In Java 7:

            <java version="1.7.0_04" class="java.beans.XMLDecoder">
             <void id="MBeanLoader0" property="owner"/>
             <object class="wt.jmx.core.mbeans.Emailer" id="Emailer0">
              <void id="ArrayList0" property="emailLists">
               <void method="add">
                <object class="wt.jmx.core.mbeans.EmailList">
                 <object idref="Emailer0">
                  <void property="emailLists">
                   <object idref="ArrayList0"/>
                  </void>
                  <void property="ownerMBean">
                   <object idref="MBeanLoader0"/>
                  </void>
                 </object>
                 <string>JMX-Administrators</string>
                 <void property="addressList">
                  <string>###@###.###</string>
                 </void>
                </object>
               </void>
              </void>
             </object>
             ...

        Java 7's output very slightly more verbose but it also seems to be "eating
        its own tail" more than the Java 6 output, i.e. it's trying to specify
        the emailLists property to be ArrayList0 in the midst of creating ArrayList0.
        The <object idref="Emailer0"> and subsequent <string>JMX-Administrators</string>
        elements are due to setting a persistence delegate of
        "new DefaultPersistenceDelegate( new String[] { "emailer", "name" } )"
        for the EmailList class.

        This change was simply ugly, but the result is that XMLDecoder fails to add
        the EmailList instance to the Emailer instance, so something seems quite broken here.

        Steps to Reproduce (be specific):

        After changing ~70 classes, can once again persist the objects via XMLEncoder.
        The output is, however, substantially different than that produced with Java 6.
        That's fine *but* also get numerous exceptions when reading this XML in with XMLDecoder.
        These are output by the exception listener and are of the form:

        java.lang.NullPointerException: target should not be null
            at java.beans.Statement.invokeInternal(Statement.java:201)
            at java.beans.Statement.access$000(Statement.java:58)
            at java.beans.Statement$2.run(Statement.java:185)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.beans.Statement.invoke(Statement.java:182)
            at java.beans.Expression.getValue(Expression.java:153)
            at com.sun.beans.decoder.ObjectElementHandler.getValueObject(ObjectElementHandler.java:166)
            at com.sun.beans.decoder.NewElementHandler.getValueObject(NewElementHandler.java:123)
            at com.sun.beans.decoder.ElementHandler.endElement(ElementHandler.java:169)
            at com.sun.beans.decoder.DocumentHandler.endElement(DocumentHandler.java:305)
            at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
            at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
            at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
            at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
            at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
            at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
            at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
            at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
            at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
            at org.apache.xerces.jaxp.SAXParserImpl.parse(Unknown Source)
            at com.sun.beans.decoder.DocumentHandler.parse(DocumentHandler.java:356)
            at java.beans.XMLDecoder.parsingComplete(XMLDecoder.java:192)
            at java.beans.XMLDecoder.readObject(XMLDecoder.java:238)
                ...

        One piece that may not be 100% obvious from the XML:

            public synchronized Collection<EmailList> getEmailLists()
            {
              return ( new ArrayList<>( emailLists.values() ) );
            }

            public synchronized void setEmailLists( final Collection<EmailList> newEmailLists )
            {
              for ( EmailList emailList : emailLists.values() )
                emailList.deregister();
              emailLists.clear();
              for ( EmailList inEmailList : newEmailLists )
                addEmailList( inEmailList );
            }

        the nuances here may explain why the new XML fails --

        in that setEmailLists() doesn't literally assign the incoming Collection
        reference to a field but rather clears its internal collection and then
        copies each element from the incoming Collection.

        It would seem that XMLEncoder should work fine with an implementation like this --
        and it did all the way through Java 5 and 6. Reading the Java 7 generation XML,
        however, it would seem that it attempts to assign this Collection to the
        Emailer object before its first element has been successfully created,
        which is clearly not right.
        Seems it is a regression after the 6921644 fix.
        We should set ArrayList later, when it will be initialized.

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                malenkov Sergey Malenkov (Inactive)
                Reporter:
                tyao Ting-Yun Ingrid Yao (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: