1 Reply Latest reply on Apr 9, 2006 5:49 PM by starksm64

    Deserialization of dynamic proxy classes

    jcoffee

      Hi,

      I recently found that SpyObjectMessage is not able to properly deserialize proxy classes. A closer look at the implementation shows that the classloader issue has well been addressed, but for ordinary classes only. The getObject() method defines a subclass of ObjectInputStream reimplementing the resolveClass() method using the context classloader rather than the default one traced from the execution stack. I would suggest to extend this ObjectInputStream subclass as shown below. I've patched this in the jbossmq.jar and everything is fine now.

      Is this a known issue? How will JBoss Messaging/JBoss AS 5 behave in this point?

      public Serializable getObject() throws JMSException {
      
       Serializable retVal = null;
       try {
       if (null != objectBytes) {
       if (isByteArray) {
       retVal = new byte[objectBytes.length];
       System.arraycopy(objectBytes, 0, retVal, 0, objectBytes.length);
       } else {
      
       /**
       * Default implementation ObjectInputStream does not work well
       * when running an a micro kernal style app-server like JBoss.
       * We need to look for the Class in the context class loader and
       * not in the System classloader.
       *
       * Would this be done better by using a MarshaedObject??
       */
       class ObjectInputStreamExt extends ObjectInputStream {
       ObjectInputStreamExt(InputStream is) throws IOException {
       super(is);
       }
      
       protected Class resolveClass(ObjectStreamClass v) throws IOException,
       ClassNotFoundException {
       return Classes.loadClass(v.getName());
       }
      
       /** Must reolve proxy classes with the context class loader too! */
       protected Class resolveProxyClass(String[] interfaces)
       throws IOException, ClassNotFoundException {
       ClassLoader contextLoader = Thread.currentThread()
       .getContextClassLoader();
       Class[] classObjs = Classes.convertToJavaClasses(Arrays.asList(
       interfaces).iterator(), contextLoader);
       return Proxy.getProxyClass(contextLoader, (Class<?>[]) classObjs);
       }
       }
       ObjectInputStream input = new ObjectInputStreamExt(new ByteArrayInputStream(
       objectBytes));
       retVal = (Serializable) input.readObject();
       input.close();
       }
       }
       } catch (ClassNotFoundException e) {
       throw new MessageFormatException("ClassNotFoundException: " + e.getMessage());
       } catch (IOException e) {
       throw new MessageFormatException("IOException: " + e.getMessage());
       }
       return retVal;
      }