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;
}