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

Wrong (de)serialization for the class javax.management.MBeanFeatureInfo

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P5 P5
    • 8
    • 6u24
    • core-svc

      FULL PRODUCT VERSION :
      $ java -version
      java version "1.6.0_24"
      Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
      Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux benoitf 2.6.32-5-amd64 #1 SMP Wed Jan 12 03:40:32 UTC 2011 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      Since Java SE 6, the class javax.management.MBeanFeatureInfo has readObject and writeObject method in order to manage itself its serialization

      By using Jacorb implementation for iiop, when we try to get MBeanInfo on objects, there are Marshalling errors.
      This is because it can't deserialize the object that has been serialized.

      REGRESSION. Last worked in version 5.0

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Download JOnAS 5.2 Application server (http://jonas.ow2.org)
      Switch to iiop/jacorb protocol : change JONAS_ROOT/conf/carol.properties (protocol = iiop instead of jrmp)

      Then launch JOnAS with the "jonas start" command

      Once JOnAS is started, compile the given class (see attached)


      And package it into a jar (with the Main-Class attribute in the manifest file) and launch it with "jclient <name of the jar file>"



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      When performing the previous commands, we're expecting to have the list of attributes and data.
      But we got an error
      ACTUAL -
      There is a marshalling error thrown by Jacorb IIOP implementation

      The problem comes from the readObject and writeObject implementation of MBeanFeatureInfo class

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Caused by: java.rmi.MarshalException: CORBA MARSHAL 0 No; nested exception is:
      org.omg.CORBA.MARSHAL: unknown value tag: 0x10100 (offset=0x2f8)
      at com.sun.corba.se.impl.javax.rmi.CORBA.Util.mapSystemException(Util.java:197)
      at org.ow2.carol.util.delegate.UtilDelegateImpl.mapSystemException(UtilDelegateImpl.java:276)
      at javax.rmi.CORBA.Util.mapSystemException(Util.java:67)
      at org.ow2.easybeans.rpc.api._RMIServerRPC_Stub.getEJBResponse(Unknown Source)
      at org.ow2.easybeans.rpc.rmi.client.RMIClientRPC.sendEJBRequest(RMIClientRPC.java:105)
      ... 16 more
      Caused by: org.omg.CORBA.MARSHAL: unknown value tag: 0x10100 (offset=0x2f8)
      at org.jacorb.orb.CDRInputStream.read_value(CDRInputStream.java:2813)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.read_Array(ValueHandlerImpl.java:746)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:315)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:283)
      at org.jacorb.util.ValueHandler.readValue(ValueHandler.java:24)
      at org.jacorb.orb.CDRInputStream.read_untyped_value(CDRInputStream.java:3026)
      at org.jacorb.orb.CDRInputStream.read_typed_value(CDRInputStream.java:3126)
      at org.jacorb.orb.CDRInputStream.read_value(CDRInputStream.java:2805)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1995)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:2220)
      at com.sun.corba.se.impl.io.IIOPInputStream.defaultReadObjectDelegate(IIOPInputStream.java:584)
      at com.sun.corba.se.impl.io.InputStreamHook.defaultReadObject(InputStreamHook.java:183)
      at javax.management.MBeanInfo.readObject(MBeanInfo.java:669)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at com.sun.corba.se.impl.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1700)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputObject(IIOPInputStream.java:1218)
      at com.sun.corba.se.impl.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:400)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:317)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:283)
      at org.jacorb.util.ValueHandler.readValue(ValueHandler.java:24)
      at org.jacorb.orb.CDRInputStream.read_untyped_value(CDRInputStream.java:3026)
      at org.jacorb.orb.CDRInputStream.read_typed_value(CDRInputStream.java:3126)
      at org.jacorb.orb.CDRInputStream.read_value(CDRInputStream.java:2677)
      at org.jacorb.orb.Any.read_value(Any.java:1298)
      at org.jacorb.orb.CDRInputStream.read_any(CDRInputStream.java:731)
      at com.sun.corba.se.impl.javax.rmi.CORBA.Util.readAny(Util.java:401)
      at org.ow2.carol.util.delegate.UtilDelegateImpl.readAny(UtilDelegateImpl.java:285)
      at javax.rmi.CORBA.Util.readAny(Util.java:92)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1923)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:2220)
      at com.sun.corba.se.impl.io.IIOPInputStream.inputObject(IIOPInputStream.java:1227)
      at com.sun.corba.se.impl.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:400)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:317)
      at com.sun.corba.se.impl.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:283)
      at org.jacorb.util.ValueHandler.readValue(ValueHandler.java:24)
      at org.jacorb.orb.CDRInputStream.read_untyped_value(CDRInputStream.java:3026)
      at org.jacorb.orb.CDRInputStream.read_typed_value(CDRInputStream.java:3126)
      at org.jacorb.orb.CDRInputStream.read_value(CDRInputStream.java:2805)
      ... 18 more


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      import java.util.*;

      import javax.management.*;
      import javax.management.j2ee.Management;
      import javax.management.j2ee.ManagementHome;

      import javax.naming.InitialContext;

      import javax.rmi.PortableRemoteObject;

      public class MejbClient {

          private static final String mejbLookup = "ejb/mgmt/MEJB";

          public static void main(final String[] args) throws Exception {

              InitialContext ctx = new InitialContext();

              Object mho = ctx.lookup(mejbLookup);

              ManagementHome mejbHome = (ManagementHome)PortableRemoteObject.narrow(mho, ManagementHome.class);

              Management mejb = mejbHome.create();

              ObjectName search = new ObjectName("*:*");

              Set mos = mejb.queryNames(search, null);

              Iterator i = mos.iterator();
              
              System.out.println("-----");

              ObjectName on = (ObjectName)i.next();
              System.out.println("First ObjectName = " + on.toString());

              MBeanInfo mbi = mejb.getMBeanInfo(on);
              System.out.println("mbi.getClassName() = " + mbi.getClassName());
              System.out.println("mbi.getDescription() = " + mbi.getDescription());

              
              MBeanAttributeInfo[] attrs = mbi.getAttributes();
              for (int n = 0; n < attrs.length; n++) {
                  System.out.println(" " + attrs[n].getName());
              }
              
              System.out.println("-----");

          }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      By switching to JDK 5, there is no longer a problem as readObject and writeObject in the class javax.management.MBeanFeatureInfo are not existing.

      So by looking at the implementation code of the MBeanFeatureInfo we can see that there is a failure which can be seen with JacORB implementation which may be more strict that jrmp or other iiop implementation.

      Here is the explanation :
      In writeObject we have the following code :
              [.....]

      if (descriptor != null &&
      descriptor.getClass() == ImmutableDescriptor.class) {

      out.write(1);

      final String[] names = descriptor.getFieldNames();

      out.writeObject(names);
      out.writeObject(descriptor.getFieldValues(names));
      } else {
              [.....]

      So it means that we write always two objects : names and the result of descriptor.getFieldValues(names) method.


      So, now look at the readObject method of this class:
              [.....]
      switch (in.read()) {
      case 1:
      final String[] names = (String[])in.readObject();

      if (names.length == 0) {
      descriptor = ImmutableDescriptor.EMPTY_DESCRIPTOR;
      } else {
      final Object[] values = (Object[])in.readObject();
      descriptor = new ImmutableDescriptor(names, values);
      }

      break;
              [.....]

      Well we can see that if we have the constant 1 value, we read the names. (so we read one object)
      And then if the names.length is greater than 0 we read the next object
      The problem is here, we've written two objects and we try to read only one object if names is null

      By changing the writeObject implementation to :
             [...]
      out.write(1);

      final String[] names = descriptor.getFieldNames();
      out.writeObject(names);
                  if (names.length > 0) {
                      out.writeObject(descriptor.getFieldValues(names));
                  }
             [...]

      The code is working with Jacorb implementation.
      In this case, we're writing an object only if there are field names. We do the same thing than on the readObject where we we're loading the next object only if there are names.
      Without the if (names.length > 0) { lines, we may add more objects that the objects that we read and this lead to marshalling exceptions


      And of course, it works great with the JDK 5 as readObject/writeObject are not here in the code, so there are no error in the writeObject method

            jbachorik Jaroslav BachorĂ­k
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: