Sometimes, after we deploy our application and bundles are being uninstalled and installed, we are getting class cast exceptions where class A cannot be cast to class A. The problem is that the class loader of an instance that have already been in the memory for a while is different than a class loader of the class itself. The deployment is not affecting the bundle in which the instance is stored (in this example bundle Y).
Here is the pseudo code:
Bundle X
public class A extends B {
/* ... */
}
...
/* ... */
@Reference
private InMemoryUserTokenStore inMemoryUserTokenStore;
/* ... */
protected UsersTokenStore getTokenStore() {
return inMemoryUserTokenStore; // <- reference to service from another bundle where tokens are stored
}
/* The token is created and obtained in the same bundle */
A token = new A(...);
getTokenStore().addToken(token)
/* ... */
B token = getTokenStore().getToken(id)
((A) token).doSomething(); // <- this is when class cast exception is thrown*/
Using the debugger I've found out that the class name of token here is A, class loaders for both returns the same bundle name and id (bundle X, same ID) however they are not equal.
Bundle Y
public class InMemoryUserTokenStore implements UsersTokenStore {
/* ... */
private ConcurrentMap<String, B> tokens = new ConcurrentHashMap();
/* ... */
public B getToken(String id) {
/* ... */
return tokens.get(id); // <- instance returned here sometimes has different class loader than class A from bundle **X**
}
/* ... */
}
I'm not sure if this is a problem with OSGI or maybe some design fault on our end?