Иногда, после развертывания нашего приложения и удаления и установки пакетов, мы получаем исключения приведения класса, когда класс A не может быть приведен к классу A. Проблема заключается в том, что загрузчик класса экземпляра, который уже был в память на некоторое время отличается от загрузчика классов самого класса. Развертывание не влияет на пакет, в котором хранится экземпляр (в этом примере - пакет Y).
Вот псевдокод:
Связка 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*/
Используя отладчик, я обнаружил, что имя класса token
здесь равно A
, загрузчики классов для обоих возвращают одно и то же имя и идентификатор пакета (однако * bundle X , тот же идентификатор) они не равны.
Связка 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**
}
/* ... */
}
Я не уверен, что это проблема с OSGI или может быть какая-то ошибка в дизайне с нашей стороны?