Исключение ClassCastException из-за проблемы с загрузчиком классов

#java #osgi #classloader

#java #osgi #classloader

Вопрос:

 interface A
class B implements A
  

Я получаю ClassCastException при преобразовании B в A. Оба A и B находятся в одном пакете.

Это может быть из-за загрузчика классов. Почему изменяется загрузчик классов для одного и того же пакета? Как я могу справиться с этой проблемой?

Дополнительная информация

  • интерфейс A (т.Е. AdminService) и класс реализации B (т.Е. AdminServiceImpl) находятся в одном пакете (fusion-core)
  • Принимая во внимание, что приведение происходит в другом пакете. — Приведение не происходит напрямую. ie B b = new B(); A a = (A) b; не происходит.
  • Приведение происходит путем разрешения службы в реестре служб OSGi. ie

     AdminService adminService = getService(AdminService.class.getName(), 100); 
    public T getService(String type, long timeToWait) { 
      ServiceTracker serviceTracker = serviceRegistry.get(type); 
      if (serviceTracker == null) { 
        serviceTracker = this.registerServiceTracker(type); 
      } 
      T service = null; 
      try { 
        service = (T) serviceTracker.waitForService(timeToWait); 
      } catch (InterruptedException e) { 
        logger.error("Error while fetching service", e); 
      } return service; 
    }
      

Эпилог

Спасибо Ивану, Анджело и Би Джею. На самом деле указатель BJ помог мне устранить проблему.

В манифесте пакета, который пытался выполнить приведение, <EXPORT-PACKAGE> экспортировался пакет другого пакета, который содержал интерфейс и реализацию. Из-за этого, вероятно, один и тот же байт-код загружался двумя разными загрузчиками классов. Bundle (выполняющий приведение), вероятно, предположил, что пакет является частью самого себя, и снова загрузил байт-код!!!

Большое спасибо, ребята.

Комментарии:

1. В каком пакете находится код, который пытается выполнить приведение? В том же пакете, что и «B» и «A», или это другой пакет?

2. Как говорит Иван, нам понадобится немного больше информации. Можете ли вы показать содержимое вашего пакета и его манифеста?

3. в будущем, пожалуйста, отредактируйте свой вопрос, а не включайте соответствующие детали в комментарии.

Ответ №1:

Если код, выполняющий приведение к A, загрузил A, отличный от пакета, который определил B (и содержит A, как вы указываете), то в виртуальной машине могут быть два разных класса A. Один из пакета, определяющего B, и другой, используемый пакетом, выполняющим приведение к A.

Поскольку A является общим типом, вам необходимо убедиться, что пакет, определяющий B, и пакет, приводящий к A, используют один и тот же класс A. Они оба должны либо импортировать пакет, содержащий A, из некоторого третьего пакета, либо пакет, определяющий B, должен экспортировать пакет, содержащий A, чтобы пакет, выполняющий приведение к A, мог импортировать этот пакет.