Deserialization of dynamic proxy classes
jcoffee Apr 8, 2006 9:35 AMHi,
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; }