Член класса возвращает null после метода привязки osgi

Моя проблема в том, что в основном классе у меня есть некоторые ссылки OSGI, которые прекрасно работают, когда класс вызывается. Но после этого все ссылки стали недействительными. Когда я закрываю главное окно и вызываю метод shutdown, ссылка hubService возвращает null. Что я здесь не так делаю?

private void shutdown() {
if(hubService == null) {
    throw new NullPointerException();
}
hubService.shutdownHub(); // why is hubService null?
}

// bind hub service
public synchronized void setHubService(IHubService service) {
hubService = service;
try {
    hubService.startHub(PORT, authenticationHandler);
} catch (Exception e) {
    JOptionPane.showMessageDialog(mainFrame, e.toString(), "Server", JOptionPane.ERROR_MESSAGE);
    System.exit(0);
}
} 

// remove hub service
public synchronized void unsetHubService(IHubService service) {
hubService.shutdownHub();
hubService = null;
}

2 ответа

Если поле может быть прочитано и записано несколькими потоками, вы должны защитить доступ как для чтения, так и для записи. Ваш первый метод, shutdown, не защищает чтение hubService, так что значение hubService может меняться между первым чтением и вторым чтением. Вы не показываете объявление поля hubService. Вы можете сделать его энергозависимым или читать только при синхронизации (на том же объекте, который использовался для синхронизации при записи поля). Тогда ваша реализация выключения может выглядеть так:

private volatile IHubService hubService;
private void shutdown() {
    IHubService service = hubService; // make a copy of the field in a local variable
    if (service != null) // use local var from now on since the field could have changed
        service.shutdownHub();
}

Я предполагаю, что ваш метод выключения является методом деактивации DS? Если да, то почему вы выключаете в методе unset, а также в методе выключения?

В целом дизайн выглядит не очень хорошо. IHubService используется как фабрика и должен возвращать некоторый объект, который затем закрывается в методе деактивации. Вы сделали IHubService эффективно единственным. Поскольку он должен поступать из другого пакета, он должен обрабатывать сам свой жизненный цикл.

Поскольку вы также не используете аннотации, неясно, являются ли ваши методы set/unset статическими / динамическими и / или одиночными / множественными. В следующем коде не должно быть проблем (например, код с аннотациями bnd):

@Component public class MyImpl {
    IHubService hub;

    @Activate
    void activate() {
      hubService.startHub(PORT, authenticationHandler);
    }

    @DeActivate
    void deactivate() {
      hubService.shutdown();
    }

    @Reference
    void setHub(IHubService hub) { this.hub = hub; }
 }
Другие вопросы по тегам