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

can't deserialize java.util.GregorianCalendar

XMLWordPrintable

    • 03
    • generic, x86
    • solaris_2.6, windows_2000

        The simple CORBA example program below fails when deserializing the java.util.GregorianCalendar.

        The reason for the failure is the way java.util.Calendar is written to the stream and read back. As shown in the code snippet below, java.util.Calendar.writeObject() writes optional ZoneInfo into the stream. In the example below, the ZoneInfo is null, so nothing is actually written to the stream. The java.util.Calendar.readObject(), in turn, tries to read this optional data via stream.readObject(). If the data is not in the stream, the exception is thrown but java.util.Calendar.readObject() ignores this exception.

        However, the side effect of calling readObject on the IIOP stream ( com.sun.corba.se.internal.io.IIOPInputStream ) in the above scenario is that the offset in the stream gets corrupted. So, the next call to the readObject() of java.util.GregorianCalendar results in a failure with an exception.

        Code Snippets of java.util.Calendar readObject() and writeObject():

        writeObject(ObjectOutputStream)
        -------------------------------
             TimeZone savedZone = null;
             if (zone instanceof ZoneInfo) {
                 SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance();
                 if (stz == null) {
                   stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID());
                 }
                 savedZone = zone;
                 zone = stz;
             }
               stream.defaultWriteObject();

             if (savedZone != null) {
                 stream.writeObject(savedZone);//not written in our case as savedZone is null
                 zone = savedZone;
             }

        readObject(ObjectInputStream)
        -----------------------------

             stream.defaultReadObject();
             try {
                ZoneInfo zi = (ZoneInfo) stream.readObject();//this is wrong as ZoneInfo was never written to the stream in the first place
                 if (zi != null) {
                   zone = zi;
                 }
             } catch (Exception e) {
             //marshal exception is thrown and the stream is corrupted,SUN ignores this exception and continues.
             }

        STEPS TO REPRODUCE THE PROBLEM (jdk 1.4.2) (all files are attached in testcase.zip)
        ----------------------------------------------------------------------------------------------

        1. Extract the files to a directory and compile(javac -d . *.java)
        2. Do rmic -iiop test.HelloImpl

        3. Start the NamingService (orbd) start orbd -ORBInitialPort 1050

        4. Run the Server
          java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
          -Djava.naming.provider.url=iiop://localhost:1050
          test.HelloServer
        5. Run the Client java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
          -Djava.naming.provider.url=iiop://localhost:1050
          test.HelloClient
          6. You will see a Marshal Exception in the Server which fails to read the data that is marshaled by the Client.

        The stack of the Exception is something like this.

        org.omg.CORBA.MARSHAL: Unmarshaller requested more data after end of stream vmcid: SUN minor code: 207 completed: No
            at com.sun.corba.se.internal.iiop.BufferManagerReadStream.underflow(BufferManagerReadStream.java:56)
            at com.sun.corba.se.internal.iiop.CDRInputStream_1_1.grow(CDRInputStream_1_1.java:73)
            at com.sun.corba.se.internal.iiop.CDRInputStream_1_2.alignAndCheck(CDRInputStream_1_2.java:28)
            at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_longlong(CDRInputStream_1_0.java:409)
            at com.sun.corba.se.internal.iiop.CDRInputStream.read_longlong(CDRInputStream.java:181)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputPrimitiveField(IIOPInputStream.java:1373)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1774)
            at com.sun.corba.se.internal.io.IIOPInputStream.defaultReadObjectDelegate(IIOPInputStream.java:436)
            at com.sun.corba.se.internal.io.InputStreamHook.defaultReadObject(InputStreamHook.java:163)
            at java.util.GregorianCalendar.readObject(GregorianCalendar.java:2122)
            at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
            at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
            at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
            at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
            at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
            at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
            at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1571)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1784)
            at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
            at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
            at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
            at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
            at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1075)
            at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
            at test._HelloImpl_Tie._invoke(_HelloImpl_Tie.java:64)
            at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:352)
            at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
            at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
            at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)

        Also, having modified the java.util.Calendar.readObject() to print the ignored exception, the following exception is observed:

        org.omg.CORBA.MARSHAL: Bad string length: -110842880 vmcid: SUN minor code: 218 completed: Maybe
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.checkForNegativeLength(CDRInputStream_1_0.java:436)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.readStringOrIndirection(CDRInputStream_1_0.java:455)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_string(CDRInputStream_1_0.java:526)
           at com.sun.corba.se.internal.iiop.CDRInputStream.read_string(CDRInputStream.java:197)
           at com.sun.corba.se.internal.ior.IOR.<init>(IOR.java:161)
           at com.sun.corba.se.internal.core.IOR.<init>(IOR.java:224)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_Object(CDRInputStream_1_0.java:652)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:857)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_abstract_interface(CDRInputStream_1_0.java:851)
           at com.sun.corba.se.internal.iiop.CDRInputStream.read_abstract_interface(CDRInputStream.java:309)
           at com.sun.corba.se.internal.io.IIOPInputStream.readObjectDelegate(IIOPInputStream.java:228)
           at com.sun.corba.se.internal.io.IIOPInputStream.readObjectOverride(IIOPInputStream.java:381)
           at java.io.ObjectInputStream.readObject(ObjectInputStream.java:318)
           at java.util.Calendar.readObject(Calendar.java:1707)
           at com.sun.corba.se.internal.io.IIOPInputStream.readObject(Native Method)
           at com.sun.corba.se.internal.io.IIOPInputStream.invokeObjectReader(IIOPInputStream.java:1298)
           at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:908)
           at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
           at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
           at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
           at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
           at com.sun.corba.se.internal.io.IIOPInputStream.inputObjectField(IIOPInputStream.java:1577)
           at com.sun.corba.se.internal.io.IIOPInputStream.inputClassFields(IIOPInputStream.java:1796)
           at com.sun.corba.se.internal.io.IIOPInputStream.inputObject(IIOPInputStream.java:913)
           at com.sun.corba.se.internal.io.IIOPInputStream.simpleReadObject(IIOPInputStream.java:261)
           at com.sun.corba.se.internal.io.ValueHandlerImpl.readValueInternal(ValueHandlerImpl.java:247)
           at com.sun.corba.se.internal.io.ValueHandlerImpl.readValue(ValueHandlerImpl.java:209)
           at com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_value(CDRInputStream_1_0.java:1084)
           at com.sun.corba.se.internal.iiop.CDRInputStream.read_value(CDRInputStream.java:293)
           at test._HelloImpl_Tie._invoke(Unknown Source)
           at com.sun.corba.se.internal.corba.ServerDelegate.dispatch(ServerDelegate.java:353)
           at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:252)
           at com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.java:81)
           at com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.java:106)

        INTERESTING NOTE:
        -------------------------
        The same is not reproducible when writing/reading the same GregorianCalendar object to a conventional ObjectOutputStream. It looks like the stream doesn't get corrupted in such case. The ignored exception from java.util.Calendar.readObject() looks quite differently too:

        java.io.OptionalDataException
                at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1294)
                at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
                at java.util.Calendar.readObject(Calendar.java:1707)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
        java:39)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
        sorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:324)
                at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:838
        )
                at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1746)

                at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1
        646)
                at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
                at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
                at sertest.main(sertest.java:16)

        This leads to a conlcusion that IIOPInputStream works improperly and corrupts the stream.
        So, either IIOPInputStream or java.util.Calendar writeObject() / readObject() need to be fixed.

              minqi Yumin Qi
              ksoshals Kirill Soshalskiy (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: