Sunday, May 9, 2010

Thread Context Classloader in Deserialization - ObjectInputStream

We had uses cases, especially with OSGI where we had to use TCCL in deserialization of Object InputStream.

Sample method

public static Object getObject(byte[] bArr){
try{
ByteArrayInputStream bais = new ByteArrayInputStream(bArr);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}catch(Exception err){
err.printStackTrace();
}
return null;
}


return ois.readObject() - fails because ObjectInputStream doesnt take into consideration TCCL when deserializing.

In OSGi we need to deserialize this using TCCL because objects being deserialized are in another bundle and framework bundle canot see these classes.

Java has provided a way to solve this . We need to extend ObjectInputStream and overide the
public Class resolveClass(ObjectStreamClass desc) method.

[Since resolveClass class is protected method in ObjectInputStream ]

Code


public class MyObjectInputStream extends ObjectInputStream {

@Override
public Class resolveClass(ObjectStreamClass desc) throws IOException,
ClassNotFoundException {
ClassLoader currentTccl = null;
try {
currentTccl = Thread.currentThread().getContextClassLoader();
return currentTccl.loadClass(desc.getName());
} catch (Exception e) {
}

}
return super.resolveClass(desc);
}

public MyObjectInputStream(InputStream in) throws IOException {
super(in);
}

}

Now we can use MyObjectInputStream which ensures that TCCL will have visibility to deserialize the class.

MyObjectInputStream ois = new MyObjectInputStream(bais);
return ois.readObject();

2 comments:

Fate said...

hi, we're looking to do this very same thing. as our objects are not deserializing in OSGi. But we've noticed that our overriden resolveClass function does not get invoked from within the readObject() function. any ideas?

Sudheer Krishna said...

Sorry i did not check my blog coment for a long time .Are u still getting these error or were u able to proceed ?

 
Free Domain Names @ .co.nr!